Skip to content

Commit

Permalink
Support nested dependent parameters
Browse files Browse the repository at this point in the history
`given` will check whether attribute is declared in its scope.
If not, it raises an error.

```ruby
optional :a
given a: ->(val) { val == 'a' } do
  optional :b
  given b: ->(val) { val == 'b' } do
    requires :c
  end
end
```

In the example, `optional :a` creates a scope. `given a: ...` creates
another scope, which parent scope is the one created by `optional :a`,
and attributes `:b` declared in `optional :b` is pushed to parent scope.

The bug here is `given b: ...` cannot find `:b` in its scope. Since the
attribute `:b` is pushed to its parent scope. So, fix the code to
check attribute in its parent scope if it has parent scope.
  • Loading branch information
Darren Chang committed Nov 1, 2018
1 parent f2e0f3e commit 0b726dd
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* [#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 support in `given` for aliased params - [@darren987469](https://github.com/darren987469).
* [#1811](https://github.com/ruby-grape/grape/pull/1811): Support nested dependent parameters - [@darren987469](https://github.com/darren987469), [@andreacfm](https://github.com/andreacfm).

### 1.1.0 (8/4/2018)

Expand Down
13 changes: 9 additions & 4 deletions lib/grape/dsl/parameters.rb
Original file line number Diff line number Diff line change
Expand Up @@ -211,10 +211,15 @@ def given(*attrs, &block)
# block yet.
# @return [Boolean] whether the parameter has been defined
def declared_param?(param)
# @declared_params also includes hashes of options and such, but those
# won't be flattened out.
@declared_params.flatten.any? do |declared_param|
first_hash_key_or_param(declared_param) == param
if lateral?
# Elements of @declared_params of lateral scope are pushed in @parent. So check them in @parent.
@parent.declared_param?(param)
else
# @declared_params also includes hashes of options and such, but those
# won't be flattened out.
@declared_params.flatten.any? do |declared_param|
first_hash_key_or_param(declared_param) == param
end
end
end

Expand Down
27 changes: 27 additions & 0 deletions spec/grape/validations/params_scope_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,33 @@ def initialize(value)
end.to_not raise_error
end

it 'allows nested dependent parameters' do
subject.params do
optional :a
given a: ->(val) { val == 'a' } do
optional :b
given b: ->(val) { val == 'b' } do
optional :c
given c: ->(val) { val == 'c' } do
requires :d
end
end
end
end
subject.get('/') { declared(params).to_json }

get '/'
expect(last_response.status).to eq 200

get '/', a: 'a', b: 'b', c: 'c'
expect(last_response.status).to eq 400
expect(last_response.body).to eq 'd is missing'

get '/', a: 'a', b: 'b', c: 'c', d: 'd'
expect(last_response.status).to eq 200
expect(last_response.body).to eq({ a: 'a', b: 'b', c: 'c', d: 'd' }.to_json)
end

it 'allows aliasing of dependent parameters' do
subject.params do
optional :a
Expand Down

0 comments on commit 0b726dd

Please sign in to comment.