-
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
Fix error for hash object warnings with delegated method descriptions #938
Fix error for hash object warnings with delegated method descriptions #938
Conversation
@PanosCodes opinion ? |
lib/apipie/error_description.rb
Outdated
begin | ||
Rack::Utils.status_code(code_or_options) | ||
rescue ArgumentError | ||
nil |
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.
why nil
here? instead of code_or_options
?
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.
Preserves the old behaviour - if code_or_options
was a symbol and that symbol wasn't present in Rack::Utils::SYMBOL_TO_STATUS_CODE
then the return would be nil
. Happy to change to code_or_options
though if you think that's better - arguably it'd probably be more useful to have code_or_options
and it's closer to the "not a symbol" code path.
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.
if all tests and rubocop passes, I don't have any objections.
but I would like @PanosCodes or someone else to chime in for final approval.
831c7d8
to
b6a2e8e
Compare
I've addressed the rubocop problems - needed to introduce Fixed the specs I broke, but there's one that is failing on master for me about rack middleware - I suspect it's because it's using rack 3 now on a fresh install, so let me know if you want me to tidy it up as part of this PR or not. I've already tidied up a few things to get to running rspec + rubocop so it definitely fits - but I also don't want to scope creep or introduce loads of unnecessary change. |
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.
Nice , thank you for your time 🙏
It's not clear to me why we need rubocop-rspec_rails in this PR, could we maybe have it in a separate one ? 🤷
@@ -98,8 +98,8 @@ def required_from_path? | |||
def warn_optional_without_default_value(definition) | |||
if !required? && !definition.key?(:default) | |||
method_id = | |||
if @param_description.is_a?(Apipie::ResponseDescriptionAdapter::PropDesc) | |||
@controller_method | |||
if @controller_method.present? && @param_description.is_a?(Apipie::ResponseDescriptionAdapter::PropDesc) |
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.
Can we end up with a blank @controller_method
?
If so maybe we could add a test case for that & update the builder's YARD block to
# @param [Apipie::MethodDescription, nil] controller_method
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 admit that I haven't really dug into the "could @controller_method
be nil
" question. I added the @controller_method.present?
check because of a test failing. I don't really know if in the normal usage of these objects to define API docs you would ever have a nil
in there. But, obviously, the code doesn't actually prevent it.
I could take the check out and try to trace the test that failed a bit deeper to understand why it's able to construct the world where it's exercising these objects without a @controller_method
being set. I don't really know what else might break elsewhere if it's nil
.
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.
A nil
@controller_method
is expected if we call json_schema_for_self_describing_class
(see
apipie-rails/lib/apipie/swagger_generator.rb
Lines 36 to 43 in 4be3741
def self.json_schema_for_self_describing_class(cls, allow_nulls) | |
Apipie::Generator::Swagger::MethodDescription::ResponseSchemaService.new( | |
ResponseDescriptionAdapter.from_self_describing_class(cls), | |
allow_null: allow_nulls, | |
http_method: nil, | |
controller_method: nil | |
).to_swagger | |
end |
Apipie::Generator::Swagger::ParamDescription::Builder
with a nil
@controller_method
. I'll update the YARD block and introduce an explicit test for it being nil
.
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.
Ok, added a new commit that changes the YARD for Apipie::Generator::Swagger::ParamDescription::Builder
and puts in tests for both Apipie::Generator::Swagger::ParamDescription::Builder and Apipie::Generator::Swagger::ParamDescription::Type when emitting warnings with PropDesc
for a param_description
and nil
for a controller_method
.
The commits with |
Good to know, although it looks like gemspec still says ruby >= 2.6 and rails >= 5? Should I update those references? |
I've extracted those commits out to #939 - and also fixed the broken spec about the recorder middleware caused by using rack 3. If we can merge that then I can rebase this against that and we can focus on the two "Use |
In Apipie#865 we introduced a `method_name` method on `MethodDescription` to avoid this bug, but the commit didn't actually use that method. Sometimes the `@controller_method` object used is a `Apipie::Generator::Swagger::MethodDescription::Decorator` which is a `SimpleDelegate` onto a `Apipie::MethodDescription` and we'd expect to be able to call `method` on it, but unfortunately `method` is one of the things _not_ delegated by `SimpleDelegate` because it's a standard ruby method and so you get ArgumentError: wrong number of arguments (given 0, expected 1) when you try to call it. Using `method_name` instead avoids that so that's what we do - and now we can happily generate the swagger warnings when we have hash type objects without defined params.
b6a2e8e
to
28ba4a7
Compare
Rebased now that #939 is merged and that makes the change much smaller and contained. To address is the outstanding comment on a blank |
@h-lame if you could add a test that covers/prove its well handled that'd be most perfect. |
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.
Looking at this one more time, LGTM ! I think I will merge next week unless objections
Unlike the previous commit, this isn't strictly required as we're not calling the un-delegated `method`, but instead the warning will contain a standard `to_s` of the `@controller_method` that isn't very easy to read, like this: WARNING (105): [#<Apipie::MethodDescription:0x0000000126316f60>] -- The parameter :param is optional but default value is not specified (use :default_value => ...) By using `method_name` instead we get symmetry with the hash warning from the previous commit.
Only allowed 15 `let` or `subject`s for a given spec, and we now have 16. Removing the `with_null` memoization lets us proceed. In theory it would have allowed us to run the specs with_null set to both true and false, but in practice, we weren't, and the other memoized values _were_ useful for customising the specs.
If we're generating swagger via `SwaggerGenerator.json_schema_for_self_describing_class` we explicitly don't have a `controller_method` being passed around so we can't use it for the warnings. Introduce a test for type and builder to cover this scenario (first spotted by a failing spec for `SwaggerGenerator`) and then change the implementation to cope with it. Luckily, `Apipie::Generator::Swagger::MethodDescription::Decorator` already had a `ruby_name` implementation that handles being given `nil`, so we use that.
28ba4a7
to
6d84540
Compare
quick compare link for the last force-push Thanks |
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.
Nice job 🚀
Fix how we generate warnings about params or properties defined as Hashes without defining what keys they can have inside them.
Our swagger docs stopped working with an ArgumentError:
And it turns out it was in the
Apipie::Generator::Swagger::ParamDescription::Type#warn_hash_without_internal_typespec
method where we call@controller_method.method
and@controller_method
was aApipie::Generator::Swagger::MethodDescription::Decorator
instance instead of aApipie::MethodDescription
instance. TheDecorator
is aSimpleDelegator
onto aMethodDescription
so it should be able to callmethod
with no arguments, but it turns out thatSimpleDelegator
won't delegatemethod
because it keeps it to refer toObject#method
. In #865 we introduced themethod_name
method onMethodDescription
to address this very problem, but we didn't actually use it in all the places we needed to. This PR fixes that inwarn_hash_without_internal_typespec
where my code was breaking and inApipie::Generator::Swagger::ParamDescription::Builder#warn_optional_without_default_value
where we weren't trying to callmethod
but we probably should have been. The error here was getting#<Apipie::MethodDescription:0x0000000126316f60>
in log messages when we'd rather get the method name.See #939 for some commits in this PR that should be merged separately - they're about a set of fixes that get us to a green build on modern ruby, rack, rubocop infrastructure. For now, focus on the "Use
method_name
..." commits in this PR.