grape 1.1.0 → 1.2.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +128 -43
- data/LICENSE +1 -1
- data/README.md +394 -47
- data/UPGRADING.md +111 -0
- data/grape.gemspec +3 -1
- data/lib/grape.rb +98 -66
- data/lib/grape/api.rb +136 -175
- data/lib/grape/api/instance.rb +280 -0
- data/lib/grape/config.rb +32 -0
- data/lib/grape/dsl/callbacks.rb +20 -0
- data/lib/grape/dsl/desc.rb +39 -7
- data/lib/grape/dsl/inside_route.rb +12 -6
- data/lib/grape/dsl/middleware.rb +7 -0
- data/lib/grape/dsl/parameters.rb +9 -4
- data/lib/grape/dsl/routing.rb +5 -1
- data/lib/grape/dsl/validations.rb +4 -3
- data/lib/grape/eager_load.rb +18 -0
- data/lib/grape/endpoint.rb +42 -26
- data/lib/grape/error_formatter.rb +1 -1
- data/lib/grape/exceptions/base.rb +9 -1
- data/lib/grape/exceptions/invalid_response.rb +9 -0
- data/lib/grape/exceptions/validation_errors.rb +4 -2
- data/lib/grape/formatter.rb +1 -1
- data/lib/grape/locale/en.yml +2 -0
- data/lib/grape/middleware/auth/base.rb +2 -4
- data/lib/grape/middleware/base.rb +2 -0
- data/lib/grape/middleware/error.rb +9 -4
- data/lib/grape/middleware/helpers.rb +10 -0
- data/lib/grape/middleware/stack.rb +1 -1
- data/lib/grape/middleware/versioner/header.rb +4 -4
- data/lib/grape/parser.rb +1 -1
- data/lib/grape/request.rb +1 -1
- data/lib/grape/router/attribute_translator.rb +2 -0
- data/lib/grape/router/route.rb +2 -2
- data/lib/grape/util/base_inheritable.rb +34 -0
- data/lib/grape/util/endpoint_configuration.rb +6 -0
- data/lib/grape/util/inheritable_values.rb +5 -25
- data/lib/grape/util/lazy_block.rb +25 -0
- data/lib/grape/util/lazy_value.rb +95 -0
- data/lib/grape/util/reverse_stackable_values.rb +7 -36
- data/lib/grape/util/stackable_values.rb +19 -22
- data/lib/grape/validations/attributes_iterator.rb +5 -3
- data/lib/grape/validations/multiple_attributes_iterator.rb +11 -0
- data/lib/grape/validations/params_scope.rb +20 -14
- data/lib/grape/validations/single_attribute_iterator.rb +13 -0
- data/lib/grape/validations/types/custom_type_coercer.rb +1 -1
- data/lib/grape/validations/types/file.rb +1 -1
- data/lib/grape/validations/validator_factory.rb +6 -11
- data/lib/grape/validations/validators/all_or_none.rb +6 -13
- data/lib/grape/validations/validators/as.rb +2 -3
- data/lib/grape/validations/validators/at_least_one_of.rb +5 -13
- data/lib/grape/validations/validators/base.rb +11 -10
- data/lib/grape/validations/validators/coerce.rb +4 -0
- data/lib/grape/validations/validators/default.rb +1 -1
- data/lib/grape/validations/validators/exactly_one_of.rb +6 -23
- data/lib/grape/validations/validators/multiple_params_base.rb +14 -10
- data/lib/grape/validations/validators/mutual_exclusion.rb +6 -18
- data/lib/grape/validations/validators/same_as.rb +23 -0
- data/lib/grape/version.rb +1 -1
- data/spec/grape/api/defines_boolean_in_params_spec.rb +37 -0
- data/spec/grape/api/routes_with_requirements_spec.rb +59 -0
- data/spec/grape/api_remount_spec.rb +466 -0
- data/spec/grape/api_spec.rb +379 -1
- data/spec/grape/config_spec.rb +17 -0
- data/spec/grape/dsl/desc_spec.rb +40 -16
- data/spec/grape/dsl/middleware_spec.rb +8 -0
- data/spec/grape/dsl/routing_spec.rb +10 -0
- data/spec/grape/endpoint_spec.rb +40 -4
- data/spec/grape/exceptions/base_spec.rb +65 -0
- data/spec/grape/exceptions/invalid_response_spec.rb +11 -0
- data/spec/grape/exceptions/validation_errors_spec.rb +6 -4
- data/spec/grape/integration/rack_spec.rb +22 -6
- data/spec/grape/middleware/auth/dsl_spec.rb +3 -3
- data/spec/grape/middleware/base_spec.rb +8 -0
- data/spec/grape/middleware/exception_spec.rb +1 -1
- data/spec/grape/middleware/formatter_spec.rb +15 -5
- data/spec/grape/middleware/versioner/header_spec.rb +6 -0
- data/spec/grape/named_api_spec.rb +19 -0
- data/spec/grape/request_spec.rb +24 -0
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +29 -0
- data/spec/grape/validations/params_scope_spec.rb +184 -8
- data/spec/grape/validations/single_attribute_iterator_spec.rb +33 -0
- data/spec/grape/validations/validators/all_or_none_spec.rb +138 -30
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +173 -29
- data/spec/grape/validations/validators/coerce_spec.rb +10 -2
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +202 -38
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +184 -27
- data/spec/grape/validations/validators/same_as_spec.rb +63 -0
- data/spec/grape/validations_spec.rb +33 -21
- data/spec/spec_helper.rb +4 -1
- metadata +35 -23
- data/Appraisals +0 -32
- data/Dangerfile +0 -2
- data/Gemfile +0 -33
- data/Gemfile.lock +0 -231
- data/Guardfile +0 -10
- data/RELEASING.md +0 -111
- data/Rakefile +0 -25
- data/benchmark/simple.rb +0 -27
- data/benchmark/simple_with_type_coercer.rb +0 -22
- data/gemfiles/multi_json.gemfile +0 -35
- data/gemfiles/multi_xml.gemfile +0 -35
- data/gemfiles/rack_1.5.2.gemfile +0 -35
- data/gemfiles/rack_edge.gemfile +0 -35
- data/gemfiles/rails_3.gemfile +0 -36
- data/gemfiles/rails_4.gemfile +0 -35
- data/gemfiles/rails_5.gemfile +0 -35
- data/gemfiles/rails_edge.gemfile +0 -35
- data/pkg/grape-0.17.0.gem +0 -0
- data/pkg/grape-0.19.0.gem +0 -0
@@ -2,61 +2,218 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Grape::Validations::MutualExclusionValidator do
|
4
4
|
describe '#validate!' do
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
subject(:validate) { post path, params }
|
6
|
+
|
7
|
+
module ValidationsSpec
|
8
|
+
module MutualExclusionValidatorSpec
|
9
|
+
class API < Grape::API
|
10
|
+
rescue_from Grape::Exceptions::ValidationErrors do |e|
|
11
|
+
error!(e.errors.transform_keys! { |key| key.join(',') }, 400)
|
12
|
+
end
|
13
|
+
|
14
|
+
params do
|
15
|
+
optional :beer
|
16
|
+
optional :wine
|
17
|
+
optional :grapefruit
|
18
|
+
mutually_exclusive :beer, :wine, :grapefruit
|
19
|
+
end
|
20
|
+
post do
|
21
|
+
end
|
22
|
+
|
23
|
+
params do
|
24
|
+
optional :beer
|
25
|
+
optional :wine
|
26
|
+
optional :grapefruit
|
27
|
+
optional :other
|
28
|
+
mutually_exclusive :beer, :wine, :grapefruit
|
29
|
+
end
|
30
|
+
post 'mixed-params' do
|
31
|
+
end
|
32
|
+
|
33
|
+
params do
|
34
|
+
optional :beer
|
35
|
+
optional :wine
|
36
|
+
optional :grapefruit
|
37
|
+
mutually_exclusive :beer, :wine, :grapefruit, message: 'you should not mix beer and wine'
|
38
|
+
end
|
39
|
+
post '/custom-message' do
|
40
|
+
end
|
41
|
+
|
42
|
+
params do
|
43
|
+
requires :item, type: Hash do
|
44
|
+
optional :beer
|
45
|
+
optional :wine
|
46
|
+
optional :grapefruit
|
47
|
+
mutually_exclusive :beer, :wine, :grapefruit
|
48
|
+
end
|
49
|
+
end
|
50
|
+
post '/nested-hash' do
|
51
|
+
end
|
52
|
+
|
53
|
+
params do
|
54
|
+
optional :item, type: Hash do
|
55
|
+
optional :beer
|
56
|
+
optional :wine
|
57
|
+
optional :grapefruit
|
58
|
+
mutually_exclusive :beer, :wine, :grapefruit
|
59
|
+
end
|
60
|
+
end
|
61
|
+
post '/nested-optional-hash' do
|
62
|
+
end
|
63
|
+
|
64
|
+
params do
|
65
|
+
requires :items, type: Array do
|
66
|
+
optional :beer
|
67
|
+
optional :wine
|
68
|
+
optional :grapefruit
|
69
|
+
mutually_exclusive :beer, :wine, :grapefruit
|
70
|
+
end
|
71
|
+
end
|
72
|
+
post '/nested-array' do
|
73
|
+
end
|
74
|
+
|
75
|
+
params do
|
76
|
+
requires :items, type: Array do
|
77
|
+
requires :nested_items, type: Array do
|
78
|
+
optional :beer, :wine, :grapefruit, type: Boolean
|
79
|
+
mutually_exclusive :beer, :wine, :grapefruit
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
post '/deeply-nested-array' do
|
84
|
+
end
|
9
85
|
end
|
10
86
|
end
|
11
87
|
end
|
12
|
-
|
13
|
-
|
88
|
+
|
89
|
+
def app
|
90
|
+
ValidationsSpec::MutualExclusionValidatorSpec::API
|
91
|
+
end
|
14
92
|
|
15
93
|
context 'when all mutually exclusive params are present' do
|
94
|
+
let(:path) { '/' }
|
16
95
|
let(:params) { { beer: true, wine: true, grapefruit: true } }
|
17
96
|
|
18
|
-
it '
|
19
|
-
|
20
|
-
|
21
|
-
|
97
|
+
it 'returns a validation error' do
|
98
|
+
validate
|
99
|
+
expect(last_response.status).to eq 400
|
100
|
+
expect(JSON.parse(last_response.body)).to eq(
|
101
|
+
'beer,wine,grapefruit' => ['are mutually exclusive']
|
102
|
+
)
|
22
103
|
end
|
23
104
|
|
24
105
|
context 'mixed with other params' do
|
25
|
-
let(:
|
106
|
+
let(:path) { '/mixed-params' }
|
107
|
+
let(:params) { { beer: true, wine: true, grapefruit: true, other: true } }
|
26
108
|
|
27
|
-
it '
|
28
|
-
|
29
|
-
|
30
|
-
|
109
|
+
it 'returns a validation error' do
|
110
|
+
validate
|
111
|
+
expect(last_response.status).to eq 400
|
112
|
+
expect(JSON.parse(last_response.body)).to eq(
|
113
|
+
'beer,wine,grapefruit' => ['are mutually exclusive']
|
114
|
+
)
|
31
115
|
end
|
32
116
|
end
|
33
117
|
end
|
34
118
|
|
35
119
|
context 'when a subset of mutually exclusive params are present' do
|
120
|
+
let(:path) { '/' }
|
36
121
|
let(:params) { { beer: true, grapefruit: true } }
|
37
122
|
|
38
|
-
it '
|
39
|
-
|
40
|
-
|
41
|
-
|
123
|
+
it 'returns a validation error' do
|
124
|
+
validate
|
125
|
+
expect(last_response.status).to eq 400
|
126
|
+
expect(JSON.parse(last_response.body)).to eq(
|
127
|
+
'beer,grapefruit' => ['are mutually exclusive']
|
128
|
+
)
|
42
129
|
end
|
43
130
|
end
|
44
131
|
|
45
|
-
context 'when
|
46
|
-
let(:
|
132
|
+
context 'when custom message is specified' do
|
133
|
+
let(:path) { '/custom-message' }
|
134
|
+
let(:params) { { beer: true, wine: true } }
|
47
135
|
|
48
|
-
it '
|
49
|
-
|
50
|
-
|
51
|
-
|
136
|
+
it 'returns a validation error' do
|
137
|
+
validate
|
138
|
+
expect(last_response.status).to eq 400
|
139
|
+
expect(JSON.parse(last_response.body)).to eq(
|
140
|
+
'beer,wine' => ['you should not mix beer and wine']
|
141
|
+
)
|
52
142
|
end
|
53
143
|
end
|
54
144
|
|
55
145
|
context 'when no mutually exclusive params are present' do
|
146
|
+
let(:path) { '/' }
|
56
147
|
let(:params) { { beer: true, somethingelse: true } }
|
57
148
|
|
58
|
-
it '
|
59
|
-
|
149
|
+
it 'does not return a validation error' do
|
150
|
+
validate
|
151
|
+
expect(last_response.status).to eq 201
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context 'when mutually exclusive params are nested inside required hash' do
|
156
|
+
let(:path) { '/nested-hash' }
|
157
|
+
let(:params) { { item: { beer: true, wine: true } } }
|
158
|
+
|
159
|
+
it 'returns a validation error with full names of the params' do
|
160
|
+
validate
|
161
|
+
expect(last_response.status).to eq 400
|
162
|
+
expect(JSON.parse(last_response.body)).to eq(
|
163
|
+
'item[beer],item[wine]' => ['are mutually exclusive']
|
164
|
+
)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
context 'when mutually exclusive params are nested inside optional hash' do
|
169
|
+
let(:path) { '/nested-optional-hash' }
|
170
|
+
|
171
|
+
context 'when params are passed' do
|
172
|
+
let(:params) { { item: { beer: true, wine: true } } }
|
173
|
+
|
174
|
+
it 'returns a validation error with full names of the params' do
|
175
|
+
validate
|
176
|
+
expect(last_response.status).to eq 400
|
177
|
+
expect(JSON.parse(last_response.body)).to eq(
|
178
|
+
'item[beer],item[wine]' => ['are mutually exclusive']
|
179
|
+
)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
context 'when params are empty' do
|
184
|
+
let(:params) { {} }
|
185
|
+
|
186
|
+
it 'does not return a validation error' do
|
187
|
+
validate
|
188
|
+
expect(last_response.status).to eq 201
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
context 'when mutually exclusive params are nested inside array' do
|
194
|
+
let(:path) { '/nested-array' }
|
195
|
+
let(:params) { { items: [{ beer: true, wine: true }, { wine: true, grapefruit: true }] } }
|
196
|
+
|
197
|
+
it 'returns a validation error with full names of the params' do
|
198
|
+
validate
|
199
|
+
expect(last_response.status).to eq 400
|
200
|
+
expect(JSON.parse(last_response.body)).to eq(
|
201
|
+
'items[0][beer],items[0][wine]' => ['are mutually exclusive'],
|
202
|
+
'items[1][wine],items[1][grapefruit]' => ['are mutually exclusive']
|
203
|
+
)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
context 'when mutually exclusive params are deeply nested' do
|
208
|
+
let(:path) { '/deeply-nested-array' }
|
209
|
+
let(:params) { { items: [{ nested_items: [{ beer: true, wine: true }] }] } }
|
210
|
+
|
211
|
+
it 'returns a validation error with full names of the params' do
|
212
|
+
validate
|
213
|
+
expect(last_response.status).to eq 400
|
214
|
+
expect(JSON.parse(last_response.body)).to eq(
|
215
|
+
'items[0][nested_items][0][beer],items[0][nested_items][0][wine]' => ['are mutually exclusive']
|
216
|
+
)
|
60
217
|
end
|
61
218
|
end
|
62
219
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Grape::Validations::SameAsValidator do
|
4
|
+
module ValidationsSpec
|
5
|
+
module SameAsValidatorSpec
|
6
|
+
class API < Grape::API
|
7
|
+
params do
|
8
|
+
requires :password
|
9
|
+
requires :password_confirmation, same_as: :password
|
10
|
+
end
|
11
|
+
post do
|
12
|
+
end
|
13
|
+
|
14
|
+
params do
|
15
|
+
requires :password
|
16
|
+
requires :password_confirmation, same_as: { value: :password, message: 'not match' }
|
17
|
+
end
|
18
|
+
post '/custom-message' do
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def app
|
25
|
+
ValidationsSpec::SameAsValidatorSpec::API
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '/' do
|
29
|
+
context 'is the same' do
|
30
|
+
it do
|
31
|
+
post '/', password: '987654', password_confirmation: '987654'
|
32
|
+
expect(last_response.status).to eq(201)
|
33
|
+
expect(last_response.body).to eq('')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'is not the same' do
|
38
|
+
it do
|
39
|
+
post '/', password: '123456', password_confirmation: 'whatever'
|
40
|
+
expect(last_response.status).to eq(400)
|
41
|
+
expect(last_response.body).to eq('password_confirmation is not the same as password')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '/custom-message' do
|
47
|
+
context 'is the same' do
|
48
|
+
it do
|
49
|
+
post '/custom-message', password: '987654', password_confirmation: '987654'
|
50
|
+
expect(last_response.status).to eq(201)
|
51
|
+
expect(last_response.body).to eq('')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'is not the same' do
|
56
|
+
it do
|
57
|
+
post '/custom-message', password: '123456', password_confirmation: 'whatever'
|
58
|
+
expect(last_response.status).to eq(400)
|
59
|
+
expect(last_response.body).to eq('password_confirmation not match')
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -540,7 +540,10 @@ describe Grape::Validations do
|
|
540
540
|
]
|
541
541
|
|
542
542
|
expect(last_response.status).to eq(400)
|
543
|
-
expect(last_response.body).to eq(
|
543
|
+
expect(last_response.body).to eq(
|
544
|
+
'children[0][parents][0][name] is missing, ' \
|
545
|
+
'children[1][parents][0][name] is missing'
|
546
|
+
)
|
544
547
|
end
|
545
548
|
|
546
549
|
it 'safely handles empty arrays and blank parameters' do
|
@@ -548,7 +551,14 @@ describe Grape::Validations do
|
|
548
551
|
# should actually return 200, since an empty array is valid.
|
549
552
|
get '/within_array', children: []
|
550
553
|
expect(last_response.status).to eq(400)
|
551
|
-
expect(last_response.body).to eq(
|
554
|
+
expect(last_response.body).to eq(
|
555
|
+
'children[0][name] is missing, ' \
|
556
|
+
'children[0][parents] is missing, ' \
|
557
|
+
'children[0][parents] is invalid, ' \
|
558
|
+
'children[0][parents][0][name] is missing, ' \
|
559
|
+
'children[0][parents][0][name] is empty'
|
560
|
+
)
|
561
|
+
|
552
562
|
get '/within_array', children: [name: 'Jay']
|
553
563
|
expect(last_response.status).to eq(400)
|
554
564
|
expect(last_response.body).to eq('children[0][parents] is missing')
|
@@ -1013,7 +1023,7 @@ describe Grape::Validations do
|
|
1013
1023
|
expect(last_response.body).to eq('custom is not custom with options!')
|
1014
1024
|
end
|
1015
1025
|
end
|
1016
|
-
end
|
1026
|
+
end
|
1017
1027
|
|
1018
1028
|
context 'named' do
|
1019
1029
|
context 'can be defined' do
|
@@ -1223,7 +1233,9 @@ describe Grape::Validations do
|
|
1223
1233
|
end
|
1224
1234
|
get '/custom_message/mutually_exclusive', beer: 'true', wine: 'true', nested: { scotch: 'true', aquavit: 'true' }, nested2: [{ scotch2: 'true' }, { scotch2: 'true', aquavit2: 'true' }]
|
1225
1235
|
expect(last_response.status).to eq(400)
|
1226
|
-
expect(last_response.body).to eq
|
1236
|
+
expect(last_response.body).to eq(
|
1237
|
+
'beer, wine are mutually exclusive pass only one, nested[scotch], nested[aquavit] are mutually exclusive pass only one, nested2[1][scotch2], nested2[1][aquavit2] are mutually exclusive pass only one'
|
1238
|
+
)
|
1227
1239
|
end
|
1228
1240
|
end
|
1229
1241
|
|
@@ -1249,7 +1261,7 @@ describe Grape::Validations do
|
|
1249
1261
|
|
1250
1262
|
get '/mutually_exclusive', beer: 'true', wine: 'true', nested: { scotch: 'true', aquavit: 'true' }, nested2: [{ scotch2: 'true' }, { scotch2: 'true', aquavit2: 'true' }]
|
1251
1263
|
expect(last_response.status).to eq(400)
|
1252
|
-
expect(last_response.body).to eq 'beer, wine are mutually exclusive, scotch, aquavit are mutually exclusive, scotch2, aquavit2 are mutually exclusive'
|
1264
|
+
expect(last_response.body).to eq 'beer, wine are mutually exclusive, nested[scotch], nested[aquavit] are mutually exclusive, nested2[1][scotch2], nested2[1][aquavit2] are mutually exclusive'
|
1253
1265
|
end
|
1254
1266
|
end
|
1255
1267
|
|
@@ -1318,7 +1330,7 @@ describe Grape::Validations do
|
|
1318
1330
|
optional :beer
|
1319
1331
|
optional :wine
|
1320
1332
|
optional :juice
|
1321
|
-
exactly_one_of :beer, :wine, :juice, message:
|
1333
|
+
exactly_one_of :beer, :wine, :juice, message: 'are missing, exactly one parameter is required'
|
1322
1334
|
end
|
1323
1335
|
get '/exactly_one_of' do
|
1324
1336
|
'exactly_one_of works!'
|
@@ -1352,7 +1364,7 @@ describe Grape::Validations do
|
|
1352
1364
|
it 'errors when two or more are present' do
|
1353
1365
|
get '/custom_message/exactly_one_of', beer: 'string', wine: 'anotherstring'
|
1354
1366
|
expect(last_response.status).to eq(400)
|
1355
|
-
expect(last_response.body).to eq 'beer, wine are
|
1367
|
+
expect(last_response.body).to eq 'beer, wine, juice are missing, exactly one parameter is required'
|
1356
1368
|
end
|
1357
1369
|
end
|
1358
1370
|
|
@@ -1371,7 +1383,7 @@ describe Grape::Validations do
|
|
1371
1383
|
it 'errors when two or more are present' do
|
1372
1384
|
get '/exactly_one_of', beer: 'string', wine: 'anotherstring'
|
1373
1385
|
expect(last_response.status).to eq(400)
|
1374
|
-
expect(last_response.body).to eq 'beer, wine are
|
1386
|
+
expect(last_response.body).to eq 'beer, wine, juice are missing, exactly one parameter must be provided'
|
1375
1387
|
end
|
1376
1388
|
end
|
1377
1389
|
|
@@ -1399,7 +1411,7 @@ describe Grape::Validations do
|
|
1399
1411
|
it 'errors when none are present' do
|
1400
1412
|
get '/exactly_one_of_nested'
|
1401
1413
|
expect(last_response.status).to eq(400)
|
1402
|
-
expect(last_response.body).to eq 'nested is missing, beer_nested, wine_nested, juice_nested are missing, exactly one parameter must be provided'
|
1414
|
+
expect(last_response.body).to eq 'nested is missing, nested[beer_nested], nested[wine_nested], nested[juice_nested] are missing, exactly one parameter must be provided'
|
1403
1415
|
end
|
1404
1416
|
|
1405
1417
|
it 'succeeds when one is present' do
|
@@ -1411,7 +1423,7 @@ describe Grape::Validations do
|
|
1411
1423
|
it 'errors when two or more are present' do
|
1412
1424
|
get '/exactly_one_of_nested', nested: { beer_nested: 'string' }, nested2: [{ beer_nested2: 'string', wine_nested2: 'anotherstring' }]
|
1413
1425
|
expect(last_response.status).to eq(400)
|
1414
|
-
expect(last_response.body).to eq 'beer_nested2, wine_nested2 are
|
1426
|
+
expect(last_response.body).to eq 'nested2[0][beer_nested2], nested2[0][wine_nested2], nested2[0][juice_nested2] are missing, exactly one parameter must be provided'
|
1415
1427
|
end
|
1416
1428
|
end
|
1417
1429
|
end
|
@@ -1485,16 +1497,16 @@ describe Grape::Validations do
|
|
1485
1497
|
before :each do
|
1486
1498
|
subject.params do
|
1487
1499
|
requires :nested, type: Hash do
|
1488
|
-
optional :
|
1489
|
-
optional :
|
1490
|
-
optional :
|
1491
|
-
at_least_one_of :
|
1500
|
+
optional :beer
|
1501
|
+
optional :wine
|
1502
|
+
optional :juice
|
1503
|
+
at_least_one_of :beer, :wine, :juice
|
1492
1504
|
end
|
1493
1505
|
optional :nested2, type: Array do
|
1494
|
-
optional :
|
1495
|
-
optional :
|
1496
|
-
optional :
|
1497
|
-
at_least_one_of :
|
1506
|
+
optional :beer
|
1507
|
+
optional :wine
|
1508
|
+
optional :juice
|
1509
|
+
at_least_one_of :beer, :wine, :juice
|
1498
1510
|
end
|
1499
1511
|
end
|
1500
1512
|
subject.get '/at_least_one_of_nested' do
|
@@ -1505,17 +1517,17 @@ describe Grape::Validations do
|
|
1505
1517
|
it 'errors when none are present' do
|
1506
1518
|
get '/at_least_one_of_nested'
|
1507
1519
|
expect(last_response.status).to eq(400)
|
1508
|
-
expect(last_response.body).to eq 'nested is missing,
|
1520
|
+
expect(last_response.body).to eq 'nested is missing, nested[beer], nested[wine], nested[juice] are missing, at least one parameter must be provided'
|
1509
1521
|
end
|
1510
1522
|
|
1511
1523
|
it 'does not error when one is present' do
|
1512
|
-
get '/at_least_one_of_nested', nested: {
|
1524
|
+
get '/at_least_one_of_nested', nested: { beer: 'string' }, nested2: [{ beer: 'string' }]
|
1513
1525
|
expect(last_response.status).to eq(200)
|
1514
1526
|
expect(last_response.body).to eq 'at_least_one_of works!'
|
1515
1527
|
end
|
1516
1528
|
|
1517
1529
|
it 'does not error when two are present' do
|
1518
|
-
get '/at_least_one_of_nested', nested: {
|
1530
|
+
get '/at_least_one_of_nested', nested: { beer: 'string', wine: 'string' }, nested2: [{ beer: 'string', wine: 'string' }]
|
1519
1531
|
expect(last_response.status).to eq(200)
|
1520
1532
|
expect(last_response.body).to eq 'at_least_one_of works!'
|
1521
1533
|
end
|