grape 1.1.0 → 1.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|