Skip to content

Commit 89591f2

Browse files
committed
Merge pull request #886 from jrichter1/required_params_type
Make the type in group of required params required (#722)
2 parents f3fe0eb + 2e64114 commit 89591f2

File tree

12 files changed

+143
-20
lines changed

12 files changed

+143
-20
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Next Release
77
* [#879](https://github.com/intridea/grape/pull/879): The `route_info` value is no longer included in `params` Hash - [@rodzyn](https://github.com/rodzyn).
88
* [#881](https://github.com/intridea/grape/issues/881): Fixed `Grape::Validations::ValuesValidator` support for `Range` type - [@ajvondrak](https://github.com/ajvondrak).
99
* [#901](https://github.com/intridea/grape/pull/901): Fix: callbacks defined in a version block are only called for the routes defined in that block - [@kushkella](https://github.com/kushkella).
10+
* [#886](https://github.com/intridea/grape/pull/886): Group of parameters made to require an explicit type of Hash or Array - [@jrichter1](https://github.com/jrichter1).
1011
* Your contribution here.
1112

1213
0.10.1 (12/28/2014)

UPGRADING.md

+8
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ Callbacks defined in a version block are only called for the routes defined in t
2626

2727
See [#901](https://github.com/intridea/grape/pull/901) for more information.
2828

29+
30+
#### Make type of group of parameters required
31+
32+
Groups of parameters now require their type to be set explicitly as Array or Hash.
33+
Not setting the type now results in MissingGroupTypeError, unsupported type will raise UnsupportedTypeError.
34+
35+
See [#886](https://github.com/intridea/grape/pull/886) for more information.
36+
2937
### Upgrading to >= 0.10.1
3038

3139
#### Changes to `declared(params, include_missing: false)`

lib/grape.rb

+2
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ module Exceptions
5555
autoload :UnknownOptions, 'grape/exceptions/unknown_options'
5656
autoload :InvalidWithOptionForRepresent, 'grape/exceptions/invalid_with_option_for_represent'
5757
autoload :IncompatibleOptionValues, 'grape/exceptions/incompatible_option_values'
58+
autoload :MissingGroupTypeError, 'grape/exceptions/missing_group_type'
59+
autoload :UnsupportedGroupTypeError, 'grape/exceptions/unsupported_group_type'
5860
end
5961

6062
module ErrorFormatter

lib/grape/dsl/parameters.rb

+7
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@ def optional(*attrs, &block)
3838
orig_attrs = attrs.clone
3939

4040
opts = attrs.last.is_a?(Hash) ? attrs.pop : {}
41+
type = opts[:type]
42+
43+
# check type for optional parameter group
44+
if attrs && block_given?
45+
fail Grape::Exceptions::MissingGroupTypeError.new if type.nil?
46+
fail Grape::Exceptions::UnsupportedGroupTypeError.new unless [Array, Hash].include?(type)
47+
end
4148

4249
validate_attributes(attrs, opts, &block)
4350

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# encoding: utf-8
2+
module Grape
3+
module Exceptions
4+
class MissingGroupTypeError < Base
5+
def initialize
6+
super(message: compose_message('missing_group_type'))
7+
end
8+
end
9+
end
10+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# encoding: utf-8
2+
module Grape
3+
module Exceptions
4+
class UnsupportedGroupTypeError < Base
5+
def initialize
6+
super(message: compose_message('unsupported_group_type'))
7+
end
8+
end
9+
end
10+
end

lib/grape/locale/en.yml

+2
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,6 @@ en:
3333
at_least_one: 'are missing, at least one parameter must be provided'
3434
exactly_one: 'are missing, exactly one parameter must be provided'
3535
all_or_none: 'provide all or none of parameters'
36+
missing_group_type: 'group type is required'
37+
unsupported_group_type: 'group type must be Array or Hash'
3638

lib/grape/validations/params_scope.rb

+7
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,13 @@ def validate_attributes(attrs, opts, &block)
7171
end
7272

7373
def new_scope(attrs, optional = false, &block)
74+
# if required params are grouped and no type or unsupported type is provided, raise an error
75+
type = attrs[1] ? attrs[1][:type] : nil
76+
if attrs.first && !optional
77+
fail Grape::Exceptions::MissingGroupTypeError.new if type.nil?
78+
fail Grape::Exceptions::UnsupportedGroupTypeError.new unless [Array, Hash].include?(type)
79+
end
80+
7481
opts = attrs[1] || { type: Array }
7582
ParamsScope.new(api: @api, element: attrs.first, parent: self, optional: optional, type: opts[:type], &block)
7683
end

spec/grape/api_spec.rb

+3-3
Original file line numberDiff line numberDiff line change
@@ -2166,11 +2166,11 @@ def static
21662166
it 'groups nested params and prevents overwriting of params with same name in different groups' do
21672167
subject.desc 'method'
21682168
subject.params do
2169-
group :group1 do
2169+
group :group1, type: Array do
21702170
optional :param1, desc: 'group1 param1 desc'
21712171
requires :param2, desc: 'group1 param2 desc'
21722172
end
2173-
group :group2 do
2173+
group :group2, type: Array do
21742174
optional :param1, desc: 'group2 param1 desc'
21752175
requires :param2, desc: 'group2 param2 desc'
21762176
end
@@ -2190,7 +2190,7 @@ def static
21902190
subject.desc 'nesting'
21912191
subject.params do
21922192
requires :root_param, desc: 'root param'
2193-
group :nested do
2193+
group :nested, type: Array do
21942194
requires :nested_param, desc: 'nested param'
21952195
end
21962196
end

spec/grape/validations/params_scope_spec.rb

+76
Original file line numberDiff line numberDiff line change
@@ -102,4 +102,80 @@ def app
102102
end
103103
end
104104
end
105+
106+
context 'parameters in group' do
107+
it 'errors when no type is provided' do
108+
expect do
109+
subject.params do
110+
group :a do
111+
requires :b
112+
end
113+
end
114+
end.to raise_error Grape::Exceptions::MissingGroupTypeError
115+
116+
expect do
117+
subject.params do
118+
optional :a do
119+
requires :b
120+
end
121+
end
122+
end.to raise_error Grape::Exceptions::MissingGroupTypeError
123+
end
124+
125+
it 'allows Hash as type' do
126+
subject.params do
127+
group :a, type: Hash do
128+
requires :b
129+
end
130+
end
131+
subject.get('/group') { 'group works' }
132+
get '/group', a: { b: true }
133+
expect(last_response.status).to eq(200)
134+
expect(last_response.body).to eq('group works')
135+
136+
subject.params do
137+
optional :a, type: Hash do
138+
requires :b
139+
end
140+
end
141+
get '/optional_type_hash'
142+
end
143+
144+
it 'allows Array as type' do
145+
subject.params do
146+
group :a, type: Array do
147+
requires :b
148+
end
149+
end
150+
subject.get('/group') { 'group works' }
151+
get '/group', a: [{ b: true }]
152+
expect(last_response.status).to eq(200)
153+
expect(last_response.body).to eq('group works')
154+
155+
subject.params do
156+
optional :a, type: Array do
157+
requires :b
158+
end
159+
end
160+
get '/optional_type_array'
161+
end
162+
163+
it 'errors with an unsupported type' do
164+
expect do
165+
subject.params do
166+
group :a, type: Set do
167+
requires :b
168+
end
169+
end
170+
end.to raise_error Grape::Exceptions::UnsupportedGroupTypeError
171+
172+
expect do
173+
subject.params do
174+
optional :a, type: Set do
175+
requires :b
176+
end
177+
end
178+
end.to raise_error Grape::Exceptions::UnsupportedGroupTypeError
179+
end
180+
end
105181
end

spec/grape/validations/validators/values_spec.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ class API < Grape::API
7171
end
7272

7373
params do
74-
optional :optional do
74+
optional :optional, type: Array do
7575
requires :type, values: %w(a b)
7676
end
7777
end

spec/grape/validations_spec.rb

+16-16
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ def define_requires_none
228228

229229
it 'adds to declared parameters' do
230230
subject.params do
231-
requires :items do
231+
requires :items, type: Array do
232232
requires :key
233233
end
234234
end
@@ -272,7 +272,7 @@ def define_requires_none
272272

273273
it 'adds to declared parameters' do
274274
subject.params do
275-
requires :items do
275+
requires :items, type: Array do
276276
requires :key
277277
end
278278
end
@@ -283,7 +283,7 @@ def define_requires_none
283283
context 'group' do
284284
before do
285285
subject.params do
286-
group :items do
286+
group :items, type: Array do
287287
requires :key
288288
end
289289
end
@@ -306,7 +306,7 @@ def define_requires_none
306306

307307
it 'adds to declared parameters' do
308308
subject.params do
309-
group :items do
309+
group :items, type: Array do
310310
requires :key
311311
end
312312
end
@@ -319,7 +319,7 @@ def define_requires_none
319319

320320
before do
321321
subject.params do
322-
optional :items do
322+
optional :items, type: Array do
323323
optional :key1, type: String
324324
optional :key2, type: String
325325
end
@@ -395,9 +395,9 @@ def validate_param!(attr_name, params)
395395
context 'validation within arrays' do
396396
before do
397397
subject.params do
398-
group :children do
398+
group :children, type: Array do
399399
requires :name
400-
group :parents do
400+
group :parents, type: Array do
401401
requires :name
402402
end
403403
end
@@ -457,7 +457,7 @@ def validate_param!(attr_name, params)
457457
context 'with block param' do
458458
before do
459459
subject.params do
460-
requires :planets do
460+
requires :planets, type: Array do
461461
requires :name
462462
end
463463
end
@@ -469,7 +469,7 @@ def validate_param!(attr_name, params)
469469
end
470470

471471
subject.params do
472-
group :stars do
472+
group :stars, type: Array do
473473
requires :name
474474
end
475475
end
@@ -482,7 +482,7 @@ def validate_param!(attr_name, params)
482482

483483
subject.params do
484484
requires :name
485-
optional :moons do
485+
optional :moons, type: Array do
486486
requires :name
487487
end
488488
end
@@ -549,9 +549,9 @@ def validate_param!(attr_name, params)
549549
context 'validation within arrays with JSON' do
550550
before do
551551
subject.params do
552-
group :children do
552+
group :children, type: Array do
553553
requires :name
554-
group :parents do
554+
group :parents, type: Array do
555555
requires :name
556556
end
557557
end
@@ -630,7 +630,7 @@ def validate_param!(attr_name, params)
630630

631631
it 'adds to declared parameters' do
632632
subject.params do
633-
optional :items do
633+
optional :items, type: Array do
634634
requires :key
635635
end
636636
end
@@ -692,10 +692,10 @@ def validate_param!(attr_name, params)
692692

693693
it 'adds to declared parameters' do
694694
subject.params do
695-
optional :items do
695+
optional :items, type: Array do
696696
requires :key
697-
optional(:optional_subitems) { requires :value }
698-
requires(:required_subitems) { requires :value }
697+
optional(:optional_subitems, type: Array) { requires :value }
698+
requires(:required_subitems, type: Array) { requires :value }
699699
end
700700
end
701701
expect(subject.route_setting(:declared_params)).to eq([items: [:key, { optional_subitems: [:value] }, { required_subitems: [:value] }]])

0 commit comments

Comments
 (0)