-
Notifications
You must be signed in to change notification settings - Fork 463
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
For discussion: proposal for describing responses #588
Conversation
First of all thanks @elasti-ron for the proposal: I like it very much. Two suggestions:
returns do
param_group :user
param_group :user_response
end What do you think? |
Also, let me invite @tstrachota and @mbacovsky for more eyes having on it. |
Thanks @iNecas - I like both of your suggestions. One thing that should be explicitly stated is the exact structure of a JSON response given a To maintain consistency with how input definitions are handled, I would expect that a For example, the following DSL: param_group :user do
param :name, String
end
param_group :user_response do
property :vote, Boolean
end
returns do
param_group :user
param_group :user_response
end would describe a JSON response that might look something like this: {
"name": "Joe",
"vote": true
} |
Yes, that's how multiple param_groups for api description currently should work as well |
Great. I'll share some experimental implementation code soon to get your thoughts and insights. |
I pushed an update with a preliminary implementation. It includes the first 3 elements of the proposal (i.e., using a Please take a look at the new Would love to get your feedback. |
Now also with |
@iNecas - the latest commit includes the 'adapter' mechanism, but as an internal feature, allowing for clearer syntax (I think). In the original proposal, future integration with Grape::Entity would have looked as follows: # entity defined using Grape::Entity
class UserView < Grape::Entity
expose :id, documentation: {type: Integer, desc: "user id", required: true}
expose :name
end
# API defined using Apipie
# where 'from_grape_entity' is an adapter that exposes the contents of the entity
# as if it were an Apipie::ParamDescription object
api :GET, "/users", "Get all user records"
returns :array_of => from_grape_entity(UserView), :desc => "the requested user records" The implementation in the latest commit uses a slightly different approach: instead of indicating # entity defined using Grape::Entity
class UserView < Grape::Entity
include "ApipieAdapter" # this is a hypothetical module - not part of the current version
# such a module would include a mixin that implements
# a 'describe_own_properties` method, called by Apipie
# to get information about the generated view structure
expose :id, documentation: {type: Integer, desc: "user id", required: true}
expose :name
end
# API defined using Apipie
# no need to specify the 'from_grape_entity' adapter because UserView includes the mixin
api :GET, "/users", "Get all user records"
returns :array_of => UserView, :desc => "the requested user records" Please take a look at Looking forward to your feedback. |
Added ability to define response descriptions at the resource level. BTW, I'm currently working (in a separate branch) on a feature to validate a JSON response.body against the 'returns' definition (by using the response schema in the generated swagger). Will merge into this branch after some additional cleanups. What I'm trying out there are two mechanisms, both intended to be used in a Controller test in RSpec :
|
Hi @iNecas - any thoughts on this so far? |
@iNecas Can you review this PR? |
lib/apipie/method_description.rb
Outdated
@@ -44,9 +48,10 @@ def initialize(method, resource, dsl_data) | |||
|
|||
@metadata = dsl_data[:meta] | |||
|
|||
@params_ordered = dsl_data[:params].map do |args| | |||
@params_ordered = dsl_data[:params].map { |args| |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a multilne block, please keep do...end
here.
# } | ||
# | ||
# | ||
RSpec::Matchers.define :match_field_structure do |expected| |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Were are we using those?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Used quite heavily in spec/lib/swagger/swagger_dsl_spec.rb
@@ -62,6 +64,9 @@ def initialize(method_description, name, validator, desc_or_options = nil, optio | |||
|
|||
@required = is_required? | |||
|
|||
@response_only = (@options[:only_in] == :response) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about request only
case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. I'll add support for this right after merging the 'response validation' mechanism that I'm cleaning up at the moment.
lib/apipie/dsl_definition.rb
Outdated
adapter = ResponseDescriptionAdapter.from_self_describing_class(descriptor) | ||
else | ||
begin | ||
block = Apipie.get_param_group(scope, descriptor) if descriptor |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The indentation should be preserved on two spaces
```ruby | ||
# entity defined using Grape::Entity | ||
class UserView < Grape::Entity | ||
expose :id, documentation: {type: Integer, desc: "user id", required: true} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indentation :)
lib/apipie/response_description.rb
Outdated
@@ -0,0 +1,113 @@ | |||
module Apipie | |||
|
|||
class ResponseObject |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Either nest it under ResponseDescription
or put it into separate file, so that the file naming follows the class names
Some comments inline, mainly styling one. I need still to get a bit deeper on the code wise: one of the non-style questions is the lack of |
apipie-rails.gemspec
Outdated
@@ -17,12 +17,12 @@ Gem::Specification.new do |s| | |||
s.require_paths = ["lib"] | |||
|
|||
s.add_dependency "rails", ">= 4.1" | |||
s.add_dependency "json-schema", ">= 2.8" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK we are using this only in tests, therefore it should not be a runtime dependency, unless we have a really good reason for doing so.
begin | ||
block = Apipie.get_param_group(scope, descriptor) if descriptor | ||
rescue | ||
raise "No param_group or self-describing class named #{descriptor}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What kind of exceptions do we expect here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
get_param_group
raises an exception if there is no param_group
with the specified name:
def get_param_group(controller, name)
key = "#{controller.name}##{name}"
if @param_groups.has_key?(key)
return @param_groups[key]
else
raise "param group #{key} not defined"
end
end
The new code (raising "No param_group or self-describing class named..."
) merely changes the message of the exception because the input to returns
is not limited to being a param_group
.
# | ||
# | ||
# to use this file in a controller rspec you should | ||
# require 'apipie/rspec/response_validation_helper' in the spec file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess we could put the documentation into the README, so that people find it more easily. Also, I would rather see the people adding the json-schema
depednency explicitly, rather than us adding this explicitly, as there are many folks that would not need this dependency at all.
Putting that aside, would you mind holding the whole feature out of this PR: it's already getting quite big/hard to review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure
4abff67
to
f2e2dda
Compare
I pushed a version with the response-validation feature redacted - hope this helps. BTW, it occurred to me when removing this feature that its unit tests are the only ones that check the semantic correctness of the swagger, so it would be good to get it back in soon. The unit tests that we currently have are purely syntactic: they verify that the generated swagger is valid, but they don't check that it is correct. |
Hi @iNecas - did you get a chance to look at the revised code? |
@iNecas any progress on this? |
Hi @iNecas, |
@@ -0,0 +1,244 @@ | |||
# Proposal for supporting response descriptions in Apipie |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we are getting close to merging this, would you mind turning this into the documentation inside README.rst?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Updated Apr-1] I pushed a version now with most of the README.rst work. Still need to document the Would you mind taking a look and letting me know if you have any comments?response description adapter
mechanism, but the straightforward use of the returns
and property
keywords is now there.
Sry for delays, still tweaking my time-management approach to be able to respond faster, but not quite there yet, as you see :) Anyway, I like the direction now. Last one request for turning the proposal into a readme. |
…how to document a response using an 'adapter' and/or 'self-describing class'
Hi @iNecas - just wanted to let you know that the Ruby project I'm currently working on will end on Apr 22, and my focus will turn to other things. At that time my availability to help out with this PR (and with integration of additional enhancements that I'm waiting to upload - such as response validation, generation of swagger response objects as references and a couple of other unrelated ones) will be very limited, if at all. It would be great if we could finish this process ASAP. |
Thanks. No other comments now. Merging this now and releasing new version. |
apipie-rails-0.5.8 with this change has just been released |
@iNecas Amazing, i used apipie 2 years ago and left it behind. Now i am using it again and i see the returns feature which is amazing. I am using it but can't get it to be displayed in the docs :( I will try to get this reproduced and open an issue for this |
@damuz91 |
@iNecas, I am still not getting response of the API in documents, even after adding returns block. any suggestions? |
No clue right now: I will hopefully will be able to look at this in 2 weeks, but probably not sooner, so if anyone wants to give it a try and debug it more deeply, any help would be appreciated. |
@X1ting thanks, the issue is merged now and available in 0.5.12 |
This pull request is for supporting a discussion, not for merging into the codebase (as per request from @iNecas).
Also relevant to #273