Skip to content

Commit b121d15

Browse files
authored
Merge pull request #1710 from pablonahuelgomez/make-declared-transform-to-what-is-expected
Fix wrong transformation of empty Array in declared params
2 parents c98b2f1 + c2c89ce commit b121d15

File tree

4 files changed

+59
-13
lines changed

4 files changed

+59
-13
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#### Fixes
1010

11+
* [#1710](https://github.com/ruby-grape/grape/pull/1710): Fix wrong transformation of empty Array in declared params - [@pablonahuelgomez](https://github.com/pablonahuelgomez).
1112
* Your contribution here.
1213

1314
### 1.0.1 (9/8/2017)

lib/grape/dsl/inside_route.rb

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,20 @@ def declared_array(passed_params, options, declared_params)
4747

4848
def declared_hash(passed_params, options, declared_params)
4949
declared_params.each_with_object(passed_params.class.new) do |declared_param, memo|
50-
# If it is not a Hash then it does not have children.
51-
# Find its value or set it to nil.
52-
if !declared_param.is_a?(Hash)
50+
if declared_param.is_a?(Hash)
51+
declared_param.each_pair do |declared_parent_param, declared_children_params|
52+
next unless options[:include_missing] || passed_params.key?(declared_parent_param)
53+
54+
passed_children_params = passed_params[declared_parent_param] || passed_params.class.new
55+
memo_key = optioned_param_key(declared_parent_param, options)
56+
57+
memo[memo_key] = handle_passed_param(declared_parent_param, passed_children_params) do
58+
declared(passed_children_params, options, declared_children_params)
59+
end
60+
end
61+
else
62+
# If it is not a Hash then it does not have children.
63+
# Find its value or set it to nil.
5364
has_alias = route_setting(:aliased_params) && route_setting(:aliased_params).find { |current| current[declared_param] }
5465
param_alias = has_alias[declared_param] if has_alias
5566

@@ -60,17 +71,26 @@ def declared_hash(passed_params, options, declared_params)
6071
else
6172
memo[optioned_param_key(declared_param, options)] = passed_params[declared_param]
6273
end
63-
else
64-
declared_param.each_pair do |declared_parent_param, declared_children_params|
65-
next unless options[:include_missing] || passed_params.key?(declared_parent_param)
66-
67-
passed_children_params = passed_params[declared_parent_param] || passed_params.class.new
68-
memo[optioned_param_key(declared_parent_param, options)] = declared(passed_children_params, options, declared_children_params)
69-
end
7074
end
7175
end
7276
end
7377

78+
def handle_passed_param(declared_param, passed_children_params, &_block)
79+
should_be_empty_array?(declared_param, passed_children_params) ? [] : yield
80+
end
81+
82+
def should_be_empty_array?(declared_param, passed_children_params)
83+
declared_param_is_array?(declared_param) && passed_children_params.empty?
84+
end
85+
86+
def declared_param_is_array?(declared_param)
87+
route_options_params[declared_param.to_s] && route_options_params[declared_param.to_s][:type] == 'Array'
88+
end
89+
90+
def route_options_params
91+
options[:route_options][:params] || {}
92+
end
93+
7494
def optioned_param_key(declared_param, options)
7595
options[:stringify] ? declared_param.to_s : declared_param.to_sym
7696
end

spec/grape/endpoint_spec.rb

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,9 @@ def app
295295
end
296296
end
297297
end
298+
optional :nested_arr, type: Array do
299+
optional :eighth
300+
end
298301
end
299302
end
300303

@@ -366,7 +369,7 @@ def app
366369
end
367370
get '/declared?first=present'
368371
expect(last_response.status).to eq(200)
369-
expect(JSON.parse(last_response.body).keys.size).to eq(4)
372+
expect(JSON.parse(last_response.body).keys.size).to eq(5)
370373
end
371374

372375
it 'has a optional param with default value all the time' do
@@ -408,8 +411,8 @@ def app
408411
expect(JSON.parse(last_response.body)['nested'].size).to eq 2
409412
end
410413

411-
context 'sets nested hash when the param is missing' do
412-
it 'to be array when include_missing is true' do
414+
context 'sets nested objects when the param is missing' do
415+
it 'to be a hash when include_missing is true' do
413416
subject.get '/declared' do
414417
declared(params, include_missing: true)
415418
end
@@ -419,6 +422,16 @@ def app
419422
expect(JSON.parse(last_response.body)['nested']).to be_a(Hash)
420423
end
421424

425+
it 'to be an array when include_missing is true' do
426+
subject.get '/declared' do
427+
declared(params, include_missing: true)
428+
end
429+
430+
get '/declared?first=present'
431+
expect(last_response.status).to eq(200)
432+
expect(JSON.parse(last_response.body)['nested_arr']).to be_a(Array)
433+
end
434+
422435
it 'to be nil when include_missing is false' do
423436
subject.get '/declared' do
424437
declared(params, include_missing: false)

spec/grape/validations/params_scope_spec.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,18 @@ def initialize(value)
339339
get '/optional_type_array'
340340
end
341341

342+
it 'handles missing optional Array type' do
343+
subject.params do
344+
optional :a, type: Array do
345+
requires :b
346+
end
347+
end
348+
subject.get('/test') { declared(params).to_json }
349+
get '/test'
350+
expect(last_response.status).to eq(200)
351+
expect(last_response.body).to eq('{"a":[]}')
352+
end
353+
342354
it 'errors with an unsupported type' do
343355
expect do
344356
subject.params do

0 commit comments

Comments
 (0)