Skip to content

Commit 0b726dd

Browse files
author
Darren Chang
committed
Support nested dependent parameters
`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.
1 parent f2e0f3e commit 0b726dd

File tree

3 files changed

+37
-4
lines changed

3 files changed

+37
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
* [#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).
1616
* [#1788](https://github.com/ruby-grape/grape/pull/1788): Fix route requirements bug - [@darren987469](https://github.com/darren987469), [@darrellnash](https://github.com/darrellnash).
1717
* [#1810](https://github.com/ruby-grape/grape/pull/1810): Fix support in `given` for aliased params - [@darren987469](https://github.com/darren987469).
18+
* [#1811](https://github.com/ruby-grape/grape/pull/1811): Support nested dependent parameters - [@darren987469](https://github.com/darren987469), [@andreacfm](https://github.com/andreacfm).
1819

1920
### 1.1.0 (8/4/2018)
2021

lib/grape/dsl/parameters.rb

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -211,10 +211,15 @@ def given(*attrs, &block)
211211
# block yet.
212212
# @return [Boolean] whether the parameter has been defined
213213
def declared_param?(param)
214-
# @declared_params also includes hashes of options and such, but those
215-
# won't be flattened out.
216-
@declared_params.flatten.any? do |declared_param|
217-
first_hash_key_or_param(declared_param) == param
214+
if lateral?
215+
# Elements of @declared_params of lateral scope are pushed in @parent. So check them in @parent.
216+
@parent.declared_param?(param)
217+
else
218+
# @declared_params also includes hashes of options and such, but those
219+
# won't be flattened out.
220+
@declared_params.flatten.any? do |declared_param|
221+
first_hash_key_or_param(declared_param) == param
222+
end
218223
end
219224
end
220225

spec/grape/validations/params_scope_spec.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,33 @@ def initialize(value)
495495
end.to_not raise_error
496496
end
497497

498+
it 'allows nested dependent parameters' do
499+
subject.params do
500+
optional :a
501+
given a: ->(val) { val == 'a' } do
502+
optional :b
503+
given b: ->(val) { val == 'b' } do
504+
optional :c
505+
given c: ->(val) { val == 'c' } do
506+
requires :d
507+
end
508+
end
509+
end
510+
end
511+
subject.get('/') { declared(params).to_json }
512+
513+
get '/'
514+
expect(last_response.status).to eq 200
515+
516+
get '/', a: 'a', b: 'b', c: 'c'
517+
expect(last_response.status).to eq 400
518+
expect(last_response.body).to eq 'd is missing'
519+
520+
get '/', a: 'a', b: 'b', c: 'c', d: 'd'
521+
expect(last_response.status).to eq 200
522+
expect(last_response.body).to eq({ a: 'a', b: 'b', c: 'c', d: 'd' }.to_json)
523+
end
524+
498525
it 'allows aliasing of dependent parameters' do
499526
subject.params do
500527
optional :a

0 commit comments

Comments
 (0)