Skip to content
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 alias on dependent param bug #1810

Merged
merged 2 commits into from
Oct 31, 2018
Merged

Conversation

darren987469
Copy link
Contributor

Fixes #1808

It seems like we cannot access to the value inside the proc for an alias param

requires :type, as: :action
given type: ->(val) { ActionService::ACTIONS.include?(val) } do #val not present inside the proc
  requires :comment, type: String
end

The root cause is as: :action alias would change params from { type: 'some type' } to { action: 'some type' } in as validator.

def validate_param!(attr_name, params)
params[@alias] = params[attr_name]
params.delete(attr_name)
end

When checking ->(val) { ActionService::ACTIONS.include?(val) } in the following snippet(line 61), dependency_key is still :type, so params[:type] is nil because the params is changed in previous validator.
@dependent_on.each do |dependency|
if dependency.is_a?(Hash)
dependency_key = dependency.keys[0]
proc = dependency.values[0]
return false unless proc.call(params.try(:[], dependency_key))
elsif params.respond_to?(:key?) && params.try(:[], dependency).blank?
return false
end
end

The idea to fix is let attribute name in given the same as the aliased one. That means the usage now becomes:

reuiqres :type, as: :action
given action: ->(val) { ... }

@darren987469 darren987469 changed the title Fix alias and dependent parameter Fix alias on dependent param bug Oct 30, 2018
@dblock
Copy link
Member

dblock commented Oct 30, 2018

Thanks! So what happens if I was using the unaliased param before, that is given a: in the spec below instead of given b:?

subject.params do
        optional :a, as: :b
        given b: ->(val) { val == 'x' } do
          requires :c
        end
      end

I am going to guess that without this fix given a: works, but given b: fails, and vice-versa. Could you please add a spec for this?

If that's the case we should either support both or clearly state what happens here in UPGRADING.

CHANGELOG.md Outdated
@@ -14,6 +14,7 @@
* [#1776](https://github.com/ruby-grape/grape/pull/1776): Validate response returned by the exception handler - [@darren987469](https://github.com/darren987469).
* [#1787](https://github.com/ruby-grape/grape/pull/1787): Add documented but not implemented ability to `.insert` a middleware in the stack - [@michaellennox](https://github.com/michaellennox).
* [#1788](https://github.com/ruby-grape/grape/pull/1788): Fix route requirements bug - [@darren987469](https://github.com/darren987469), [@darrellnash](https://github.com/darrellnash).
* [#1810](https://github.com/ruby-grape/grape/pull/1810): Fix alias on dependent param bug - [@darren987469](https://github.com/darren987469).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe say something more explicit? Eg. "Fix support in given for aliased params"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it is more clear.

@darren987469
Copy link
Contributor Author

darren987469 commented Oct 31, 2018

Let me describe given a:, given b: cases with or without this fix.

Without this fix case given a:

subject.params do
  optional :a, as: :b                # 'as: :b' change params form { a: 'something' } to { b: 'something' }
  given a: ->(val) { val == 'x' } do # val = params[:a] = nil, condition doesn't meet
    requires :c
  end
end
subject.get('/') { declared(params) }

get '/', a: 'x'
expect(last_response.status).to eq 400              # fail, since given condition doesn't meet 
expect(last_response.body).to eq 'c is missing' 

Without this fix case given b:

subject.params do
  optional :a, as: :b                           
  given b: ->(val) { val == 'x' } do # raise Grape::Exceptions::UnknownParameter. @declared_params in grape/lib/grape/dsl/parameters.rb is [:a], which doesn't contain :b. That why this fix try to solve.
    requires :c
  end
end

With this fix case given a:

subject.params do
  optional :a, as: :b                # 'as: :b' change params form { a: 'somthing' } to { b: 'something' }
  given a: ->(val) { val == 'x' } do # raise Grape::Exceptions::UnknownParameter.  @declared_params in grape/lib/grape/dsl/parameters.rb is now [:b], which doesn't contain :a. 
    requires :c
  end
end

With this fix case given b:

subject.params do
  optional :a, as: :b            # 'as: :b' change params form { a: 'somthing' } to { b: 'something' }               
  given b: ->(val) { val == 'x' } do # val = params[:b] 
    requires :c
  end
end

get '/', a: 'x'
expect(last_response.status).to eq 400              # success, since given condition meets
expect(last_response.body).to eq 'c is missing' 

I think it makes sense to force to use given b:. Because we change params from { a: 'something' } to { b: 'something' }.
What do you think?

expect do
subject.params do
optional :a, as: :b
given :a do
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I add a spec to show with this fix, given :a(not the aliased param :b) case.

@dblock dblock merged commit b8b85af into ruby-grape:master Oct 31, 2018
@dblock
Copy link
Member

dblock commented Oct 31, 2018

Perfect, thanks for the specs.

@darren987469 darren987469 deleted the fix_issue1808 branch October 31, 2018 11:39
basjanssen pushed a commit to basjanssen/grape that referenced this pull request Feb 28, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Params 'as' option not accessible within 'given' block proc
2 participants