grape 1.5.1 → 1.6.1
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 +57 -3
- data/CONTRIBUTING.md +1 -0
- data/README.md +50 -8
- data/UPGRADING.md +69 -0
- data/grape.gemspec +5 -5
- data/lib/grape/api/instance.rb +13 -17
- data/lib/grape/api.rb +19 -14
- data/lib/grape/cookies.rb +2 -0
- data/lib/grape/dry_types.rb +12 -0
- data/lib/grape/dsl/callbacks.rb +1 -1
- data/lib/grape/dsl/desc.rb +3 -5
- data/lib/grape/dsl/headers.rb +5 -2
- data/lib/grape/dsl/helpers.rb +7 -5
- data/lib/grape/dsl/inside_route.rb +18 -9
- data/lib/grape/dsl/middleware.rb +4 -4
- data/lib/grape/dsl/parameters.rb +4 -4
- data/lib/grape/dsl/request_response.rb +9 -6
- data/lib/grape/dsl/routing.rb +7 -6
- data/lib/grape/dsl/settings.rb +5 -5
- data/lib/grape/endpoint.rb +21 -36
- data/lib/grape/error_formatter/json.rb +2 -6
- data/lib/grape/error_formatter/xml.rb +2 -6
- data/lib/grape/exceptions/empty_message_body.rb +11 -0
- data/lib/grape/exceptions/validation.rb +2 -3
- data/lib/grape/exceptions/validation_errors.rb +1 -1
- data/lib/grape/formatter/json.rb +1 -0
- data/lib/grape/formatter/serializable_hash.rb +2 -1
- data/lib/grape/formatter/xml.rb +1 -0
- data/lib/grape/locale/en.yml +1 -1
- data/lib/grape/middleware/auth/base.rb +3 -3
- data/lib/grape/middleware/auth/dsl.rb +7 -1
- data/lib/grape/middleware/base.rb +5 -3
- data/lib/grape/middleware/error.rb +1 -1
- data/lib/grape/middleware/formatter.rb +4 -4
- data/lib/grape/middleware/stack.rb +14 -20
- data/lib/grape/middleware/versioner/accept_version_header.rb +3 -5
- data/lib/grape/middleware/versioner/header.rb +6 -4
- data/lib/grape/middleware/versioner/param.rb +1 -0
- data/lib/grape/middleware/versioner/parse_media_type_patch.rb +2 -1
- data/lib/grape/middleware/versioner/path.rb +2 -0
- data/lib/grape/parser/json.rb +1 -1
- data/lib/grape/parser/xml.rb +1 -1
- data/lib/grape/path.rb +1 -0
- data/lib/grape/request.rb +3 -0
- data/lib/grape/router/pattern.rb +1 -1
- data/lib/grape/router/route.rb +2 -2
- data/lib/grape/router.rb +6 -0
- data/lib/grape/util/inheritable_setting.rb +1 -3
- data/lib/grape/util/json.rb +2 -0
- data/lib/grape/util/lazy_value.rb +3 -2
- data/lib/grape/util/strict_hash_configuration.rb +1 -1
- data/lib/grape/validations/params_scope.rb +89 -56
- data/lib/grape/validations/types/array_coercer.rb +0 -2
- data/lib/grape/validations/types/custom_type_coercer.rb +3 -2
- data/lib/grape/validations/types/dry_type_coercer.rb +2 -11
- data/lib/grape/validations/types/invalid_value.rb +24 -0
- data/lib/grape/validations/types/json.rb +2 -3
- data/lib/grape/validations/types/primitive_coercer.rb +5 -7
- data/lib/grape/validations/types/set_coercer.rb +0 -3
- data/lib/grape/validations/types.rb +83 -12
- data/lib/grape/validations/validators/all_or_none_of_validator.rb +16 -0
- data/lib/grape/validations/validators/allow_blank_validator.rb +20 -0
- data/lib/grape/validations/validators/as_validator.rb +14 -0
- data/lib/grape/validations/validators/at_least_one_of_validator.rb +15 -0
- data/lib/grape/validations/validators/base.rb +75 -69
- data/lib/grape/validations/validators/coerce_validator.rb +75 -0
- data/lib/grape/validations/validators/default_validator.rb +51 -0
- data/lib/grape/validations/validators/exactly_one_of_validator.rb +17 -0
- data/lib/grape/validations/validators/except_values_validator.rb +24 -0
- data/lib/grape/validations/validators/multiple_params_base.rb +24 -20
- data/lib/grape/validations/validators/mutual_exclusion_validator.rb +16 -0
- data/lib/grape/validations/validators/presence_validator.rb +15 -0
- data/lib/grape/validations/validators/regexp_validator.rb +16 -0
- data/lib/grape/validations/validators/same_as_validator.rb +29 -0
- data/lib/grape/validations/validators/values_validator.rb +88 -0
- data/lib/grape/version.rb +1 -1
- data/lib/grape.rb +61 -24
- data/spec/grape/api/custom_validations_spec.rb +77 -45
- data/spec/grape/api/deeply_included_options_spec.rb +3 -3
- data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -1
- data/spec/grape/api/invalid_format_spec.rb +2 -0
- data/spec/grape/api/recognize_path_spec.rb +1 -1
- data/spec/grape/api/routes_with_requirements_spec.rb +8 -8
- data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -15
- data/spec/grape/api_remount_spec.rb +25 -19
- data/spec/grape/api_spec.rb +510 -220
- data/spec/grape/dsl/callbacks_spec.rb +2 -1
- data/spec/grape/dsl/headers_spec.rb +39 -9
- data/spec/grape/dsl/helpers_spec.rb +3 -2
- data/spec/grape/dsl/inside_route_spec.rb +6 -4
- data/spec/grape/dsl/logger_spec.rb +16 -18
- data/spec/grape/dsl/middleware_spec.rb +2 -1
- data/spec/grape/dsl/parameters_spec.rb +2 -0
- data/spec/grape/dsl/request_response_spec.rb +1 -0
- data/spec/grape/dsl/routing_spec.rb +10 -7
- data/spec/grape/endpoint/declared_spec.rb +259 -12
- data/spec/grape/endpoint_spec.rb +77 -55
- data/spec/grape/entity_spec.rb +23 -23
- data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -0
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +61 -22
- data/spec/grape/exceptions/validation_errors_spec.rb +13 -10
- data/spec/grape/exceptions/validation_spec.rb +5 -3
- data/spec/grape/extensions/param_builders/hash_spec.rb +7 -7
- data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -8
- data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -8
- data/spec/grape/integration/rack_sendfile_spec.rb +1 -1
- data/spec/grape/loading_spec.rb +8 -8
- data/spec/grape/middleware/auth/dsl_spec.rb +15 -6
- data/spec/grape/middleware/auth/strategies_spec.rb +60 -20
- data/spec/grape/middleware/base_spec.rb +24 -15
- data/spec/grape/middleware/error_spec.rb +2 -2
- data/spec/grape/middleware/exception_spec.rb +111 -161
- data/spec/grape/middleware/formatter_spec.rb +27 -6
- data/spec/grape/middleware/globals_spec.rb +7 -4
- data/spec/grape/middleware/stack_spec.rb +15 -14
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -1
- data/spec/grape/middleware/versioner/header_spec.rb +14 -13
- data/spec/grape/middleware/versioner/param_spec.rb +7 -1
- data/spec/grape/middleware/versioner/path_spec.rb +5 -1
- data/spec/grape/middleware/versioner_spec.rb +1 -1
- data/spec/grape/parser_spec.rb +4 -0
- data/spec/grape/path_spec.rb +52 -52
- data/spec/grape/presenters/presenter_spec.rb +7 -6
- data/spec/grape/request_spec.rb +6 -4
- data/spec/grape/util/inheritable_setting_spec.rb +7 -7
- data/spec/grape/util/inheritable_values_spec.rb +3 -2
- data/spec/grape/util/reverse_stackable_values_spec.rb +3 -1
- data/spec/grape/util/stackable_values_spec.rb +7 -5
- data/spec/grape/validations/instance_behaivour_spec.rb +9 -10
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +1 -0
- data/spec/grape/validations/params_scope_spec.rb +46 -10
- data/spec/grape/validations/single_attribute_iterator_spec.rb +2 -1
- data/spec/grape/validations/types/primitive_coercer_spec.rb +4 -4
- data/spec/grape/validations/types_spec.rb +8 -8
- data/spec/grape/validations/validators/all_or_none_spec.rb +50 -56
- data/spec/grape/validations/validators/allow_blank_spec.rb +136 -140
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -56
- data/spec/grape/validations/validators/coerce_spec.rb +139 -34
- data/spec/grape/validations/validators/default_spec.rb +72 -78
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -77
- data/spec/grape/validations/validators/except_values_spec.rb +3 -3
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -77
- data/spec/grape/validations/validators/presence_spec.rb +16 -1
- data/spec/grape/validations/validators/regexp_spec.rb +25 -31
- data/spec/grape/validations/validators/same_as_spec.rb +14 -20
- data/spec/grape/validations/validators/values_spec.rb +183 -178
- data/spec/grape/validations_spec.rb +99 -58
- data/spec/integration/eager_load/eager_load_spec.rb +2 -2
- data/spec/integration/multi_json/json_spec.rb +1 -1
- data/spec/integration/multi_xml/xml_spec.rb +1 -1
- data/spec/shared/versioning_examples.rb +32 -29
- data/spec/spec_helper.rb +12 -2
- data/spec/support/basic_auth_encode_helpers.rb +1 -1
- data/spec/support/versioned_helpers.rb +1 -1
- metadata +117 -115
- data/lib/grape/validations/types/build_coercer.rb +0 -94
- data/lib/grape/validations/validators/all_or_none.rb +0 -15
- data/lib/grape/validations/validators/allow_blank.rb +0 -18
- data/lib/grape/validations/validators/as.rb +0 -16
- data/lib/grape/validations/validators/at_least_one_of.rb +0 -14
- data/lib/grape/validations/validators/coerce.rb +0 -88
- data/lib/grape/validations/validators/default.rb +0 -48
- data/lib/grape/validations/validators/exactly_one_of.rb +0 -16
- data/lib/grape/validations/validators/except_values.rb +0 -22
- data/lib/grape/validations/validators/mutual_exclusion.rb +0 -15
- data/lib/grape/validations/validators/presence.rb +0 -12
- data/lib/grape/validations/validators/regexp.rb +0 -13
- data/lib/grape/validations/validators/same_as.rb +0 -26
- data/lib/grape/validations/validators/values.rb +0 -83
@@ -2,73 +2,67 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
describe Grape::Validations::AtLeastOneOfValidator do
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
class API < Grape::API
|
12
|
-
rescue_from Grape::Exceptions::ValidationErrors do |e|
|
13
|
-
error!(e.errors.transform_keys! { |key| key.join(',') }, 400)
|
14
|
-
end
|
5
|
+
describe Grape::Validations::Validators::AtLeastOneOfValidator do
|
6
|
+
let_it_be(:app) do
|
7
|
+
Class.new(Grape::API) do
|
8
|
+
rescue_from Grape::Exceptions::ValidationErrors do |e|
|
9
|
+
error!(e.errors.transform_keys! { |key| key.join(',') }, 400)
|
10
|
+
end
|
15
11
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
12
|
+
params do
|
13
|
+
optional :beer, :wine, :grapefruit
|
14
|
+
at_least_one_of :beer, :wine, :grapefruit
|
15
|
+
end
|
16
|
+
post do
|
17
|
+
end
|
22
18
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
19
|
+
params do
|
20
|
+
optional :beer, :wine, :grapefruit, :other
|
21
|
+
at_least_one_of :beer, :wine, :grapefruit
|
22
|
+
end
|
23
|
+
post 'mixed-params' do
|
24
|
+
end
|
29
25
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
26
|
+
params do
|
27
|
+
optional :beer, :wine, :grapefruit
|
28
|
+
at_least_one_of :beer, :wine, :grapefruit, message: 'you should choose something'
|
29
|
+
end
|
30
|
+
post '/custom-message' do
|
31
|
+
end
|
36
32
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
33
|
+
params do
|
34
|
+
requires :item, type: Hash do
|
35
|
+
optional :beer, :wine, :grapefruit
|
36
|
+
at_least_one_of :beer, :wine, :grapefruit, message: 'fail'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
post '/nested-hash' do
|
40
|
+
end
|
45
41
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
42
|
+
params do
|
43
|
+
requires :items, type: Array do
|
44
|
+
optional :beer, :wine, :grapefruit
|
45
|
+
at_least_one_of :beer, :wine, :grapefruit, message: 'fail'
|
46
|
+
end
|
47
|
+
end
|
48
|
+
post '/nested-array' do
|
49
|
+
end
|
54
50
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
post '/deeply-nested-array' do
|
51
|
+
params do
|
52
|
+
requires :items, type: Array do
|
53
|
+
requires :nested_items, type: Array do
|
54
|
+
optional :beer, :wine, :grapefruit
|
55
|
+
at_least_one_of :beer, :wine, :grapefruit, message: 'fail'
|
64
56
|
end
|
65
57
|
end
|
66
58
|
end
|
59
|
+
post '/deeply-nested-array' do
|
60
|
+
end
|
67
61
|
end
|
62
|
+
end
|
68
63
|
|
69
|
-
|
70
|
-
|
71
|
-
end
|
64
|
+
describe '#validate!' do
|
65
|
+
subject(:validate) { post path, params }
|
72
66
|
|
73
67
|
context 'when all restricted params are present' do
|
74
68
|
let(:path) { '/' }
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
describe Grape::Validations::CoerceValidator do
|
5
|
+
describe Grape::Validations::Validators::CoerceValidator do
|
6
6
|
subject do
|
7
7
|
Class.new(Grape::API)
|
8
8
|
end
|
@@ -23,7 +23,7 @@ describe Grape::Validations::CoerceValidator do
|
|
23
23
|
end
|
24
24
|
|
25
25
|
context 'i18n' do
|
26
|
-
after
|
26
|
+
after do
|
27
27
|
I18n.available_locales = %i[en]
|
28
28
|
I18n.locale = :en
|
29
29
|
I18n.default_locale = :en
|
@@ -31,9 +31,9 @@ describe Grape::Validations::CoerceValidator do
|
|
31
31
|
|
32
32
|
it 'i18n error on malformed input' do
|
33
33
|
I18n.available_locales = %i[en zh-CN]
|
34
|
-
I18n.load_path << File.expand_path('
|
34
|
+
I18n.load_path << File.expand_path('zh-CN.yml', __dir__)
|
35
35
|
I18n.reload!
|
36
|
-
I18n.locale = 'zh-CN'
|
36
|
+
I18n.locale = :'zh-CN'
|
37
37
|
subject.params do
|
38
38
|
requires :age, type: Integer
|
39
39
|
end
|
@@ -48,7 +48,7 @@ describe Grape::Validations::CoerceValidator do
|
|
48
48
|
|
49
49
|
it 'gives an english fallback error when default locale message is blank' do
|
50
50
|
I18n.available_locales = %i[en pt-BR]
|
51
|
-
I18n.locale = 'pt-BR'
|
51
|
+
I18n.locale = :'pt-BR'
|
52
52
|
subject.params do
|
53
53
|
requires :age, type: Integer
|
54
54
|
end
|
@@ -83,10 +83,11 @@ describe Grape::Validations::CoerceValidator do
|
|
83
83
|
context 'on custom coercion rules' do
|
84
84
|
before do
|
85
85
|
subject.params do
|
86
|
-
requires :a, types: { value: [Boolean, String], message: 'type cast is invalid' }, coerce_with: (lambda do |val|
|
87
|
-
|
86
|
+
requires :a, types: { value: [Grape::API::Boolean, String], message: 'type cast is invalid' }, coerce_with: (lambda do |val|
|
87
|
+
case val
|
88
|
+
when 'yup'
|
88
89
|
true
|
89
|
-
|
90
|
+
when 'false'
|
90
91
|
0
|
91
92
|
else
|
92
93
|
val
|
@@ -170,9 +171,9 @@ describe Grape::Validations::CoerceValidator do
|
|
170
171
|
expect(last_response.body).to eq('BigDecimal 45.1')
|
171
172
|
end
|
172
173
|
|
173
|
-
it 'Boolean' do
|
174
|
+
it 'Grape::API::Boolean' do
|
174
175
|
subject.params do
|
175
|
-
requires :boolean, type: Boolean
|
176
|
+
requires :boolean, type: Grape::API::Boolean
|
176
177
|
end
|
177
178
|
subject.post '/boolean' do
|
178
179
|
params[:boolean]
|
@@ -227,23 +228,51 @@ describe Grape::Validations::CoerceValidator do
|
|
227
228
|
expect(last_response.body).to eq('NilClass')
|
228
229
|
end
|
229
230
|
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
231
|
+
context 'a custom type' do
|
232
|
+
it 'coerces the given value' do
|
233
|
+
subject.params do
|
234
|
+
requires :uri, coerce: SecureURIOnly
|
235
|
+
end
|
236
|
+
subject.get '/secure_uri' do
|
237
|
+
params[:uri].class
|
238
|
+
end
|
239
|
+
|
240
|
+
get 'secure_uri', uri: 'https://www.example.com'
|
241
|
+
|
242
|
+
expect(last_response.status).to eq(200)
|
243
|
+
expect(last_response.body).to eq('URI::HTTPS')
|
244
|
+
|
245
|
+
get 'secure_uri', uri: 'http://www.example.com'
|
246
|
+
|
247
|
+
expect(last_response.status).to eq(400)
|
248
|
+
expect(last_response.body).to eq('uri is invalid')
|
236
249
|
end
|
237
250
|
|
238
|
-
|
251
|
+
context 'returning the InvalidValue instance when invalid' do
|
252
|
+
let(:custom_type) do
|
253
|
+
Class.new do
|
254
|
+
def self.parse(_val)
|
255
|
+
Grape::Types::InvalidValue.new('must be unique')
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
it 'uses a custom message added to the invalid value' do
|
261
|
+
type = custom_type
|
239
262
|
|
240
|
-
|
241
|
-
|
263
|
+
subject.params do
|
264
|
+
requires :name, type: type
|
265
|
+
end
|
266
|
+
subject.get '/whatever' do
|
267
|
+
params[:name].class
|
268
|
+
end
|
242
269
|
|
243
|
-
|
270
|
+
get 'whatever', name: 'Bob'
|
244
271
|
|
245
|
-
|
246
|
-
|
272
|
+
expect(last_response.status).to eq(400)
|
273
|
+
expect(last_response.body).to eq('name must be unique')
|
274
|
+
end
|
275
|
+
end
|
247
276
|
end
|
248
277
|
|
249
278
|
context 'Array' do
|
@@ -341,9 +370,9 @@ describe Grape::Validations::CoerceValidator do
|
|
341
370
|
end
|
342
371
|
end
|
343
372
|
|
344
|
-
it 'Boolean' do
|
373
|
+
it 'Grape::API::Boolean' do
|
345
374
|
subject.params do
|
346
|
-
requires :boolean, type: Boolean
|
375
|
+
requires :boolean, type: Grape::API::Boolean
|
347
376
|
end
|
348
377
|
subject.get '/boolean' do
|
349
378
|
params[:boolean].class
|
@@ -622,7 +651,7 @@ describe Grape::Validations::CoerceValidator do
|
|
622
651
|
|
623
652
|
it 'parses parameters with Array[Array[String]] type and coerce_with' do
|
624
653
|
subject.params do
|
625
|
-
requires :values, type: Array[Array[String]], coerce_with: ->(val) { val.is_a?(String) ? [val.split(
|
654
|
+
requires :values, type: Array[Array[String]], coerce_with: ->(val) { val.is_a?(String) ? [val.split(',').map(&:strip)] : val }
|
626
655
|
end
|
627
656
|
subject.post '/coerce_nested_strings' do
|
628
657
|
params[:values]
|
@@ -678,6 +707,44 @@ describe Grape::Validations::CoerceValidator do
|
|
678
707
|
expect(JSON.parse(last_response.body)).to eq([1, 1, 1, 1])
|
679
708
|
end
|
680
709
|
|
710
|
+
context 'Array type and coerce_with should' do
|
711
|
+
before do
|
712
|
+
subject.params do
|
713
|
+
optional :arr, type: Array, coerce_with: (lambda do |val|
|
714
|
+
if val.nil?
|
715
|
+
[]
|
716
|
+
else
|
717
|
+
val
|
718
|
+
end
|
719
|
+
end)
|
720
|
+
end
|
721
|
+
subject.get '/' do
|
722
|
+
params[:arr].class.to_s
|
723
|
+
end
|
724
|
+
end
|
725
|
+
|
726
|
+
it 'coerce nil value to array' do
|
727
|
+
get '/', arr: nil
|
728
|
+
|
729
|
+
expect(last_response.status).to eq(200)
|
730
|
+
expect(last_response.body).to eq('Array')
|
731
|
+
end
|
732
|
+
|
733
|
+
it 'not coerce missing field' do
|
734
|
+
get '/'
|
735
|
+
|
736
|
+
expect(last_response.status).to eq(200)
|
737
|
+
expect(last_response.body).to eq('NilClass')
|
738
|
+
end
|
739
|
+
|
740
|
+
it 'coerce array as array' do
|
741
|
+
get '/', arr: []
|
742
|
+
|
743
|
+
expect(last_response.status).to eq(200)
|
744
|
+
expect(last_response.body).to eq('Array')
|
745
|
+
end
|
746
|
+
end
|
747
|
+
|
681
748
|
it 'uses parse where available' do
|
682
749
|
subject.params do
|
683
750
|
requires :ints, type: Array, coerce_with: JSON do
|
@@ -726,13 +793,52 @@ describe Grape::Validations::CoerceValidator do
|
|
726
793
|
expect(last_response.body).to eq('3')
|
727
794
|
end
|
728
795
|
|
796
|
+
context 'Integer type and coerce_with should' do
|
797
|
+
before do
|
798
|
+
subject.params do
|
799
|
+
optional :int, type: Integer, coerce_with: (lambda do |val|
|
800
|
+
if val.nil?
|
801
|
+
0
|
802
|
+
else
|
803
|
+
val.to_i
|
804
|
+
end
|
805
|
+
end)
|
806
|
+
end
|
807
|
+
subject.get '/' do
|
808
|
+
params[:int].class.to_s
|
809
|
+
end
|
810
|
+
end
|
811
|
+
|
812
|
+
it 'coerce nil value to integer' do
|
813
|
+
get '/', int: nil
|
814
|
+
|
815
|
+
expect(last_response.status).to eq(200)
|
816
|
+
expect(last_response.body).to eq('Integer')
|
817
|
+
end
|
818
|
+
|
819
|
+
it 'not coerce missing field' do
|
820
|
+
get '/'
|
821
|
+
|
822
|
+
expect(last_response.status).to eq(200)
|
823
|
+
expect(last_response.body).to eq('NilClass')
|
824
|
+
end
|
825
|
+
|
826
|
+
it 'coerce integer as integer' do
|
827
|
+
get '/', int: 1
|
828
|
+
|
829
|
+
expect(last_response.status).to eq(200)
|
830
|
+
expect(last_response.body).to eq('Integer')
|
831
|
+
end
|
832
|
+
end
|
833
|
+
|
729
834
|
context 'Integer type and coerce_with potentially returning nil' do
|
730
835
|
before do
|
731
836
|
subject.params do
|
732
837
|
requires :int, type: Integer, coerce_with: (lambda do |val|
|
733
|
-
|
838
|
+
case val
|
839
|
+
when '0'
|
734
840
|
nil
|
735
|
-
|
841
|
+
when /^-?\d+$/
|
736
842
|
val.to_i
|
737
843
|
else
|
738
844
|
val
|
@@ -912,11 +1018,9 @@ describe Grape::Validations::CoerceValidator do
|
|
912
1018
|
end
|
913
1019
|
|
914
1020
|
context 'multiple types' do
|
915
|
-
Boolean = Grape::API::Boolean
|
916
|
-
|
917
1021
|
it 'coerces to first possible type' do
|
918
1022
|
subject.params do
|
919
|
-
requires :a, types: [Boolean, Integer, String]
|
1023
|
+
requires :a, types: [Grape::API::Boolean, Integer, String]
|
920
1024
|
end
|
921
1025
|
subject.get '/' do
|
922
1026
|
params[:a].class.to_s
|
@@ -937,7 +1041,7 @@ describe Grape::Validations::CoerceValidator do
|
|
937
1041
|
|
938
1042
|
it 'fails when no coercion is possible' do
|
939
1043
|
subject.params do
|
940
|
-
requires :a, types: [Boolean, Integer]
|
1044
|
+
requires :a, types: [Grape::API::Boolean, Integer]
|
941
1045
|
end
|
942
1046
|
subject.get '/' do
|
943
1047
|
params[:a].class.to_s
|
@@ -1096,10 +1200,11 @@ describe Grape::Validations::CoerceValidator do
|
|
1096
1200
|
context 'custom coercion rules' do
|
1097
1201
|
before do
|
1098
1202
|
subject.params do
|
1099
|
-
requires :a, types: [Boolean, String], coerce_with: (lambda do |val|
|
1100
|
-
|
1203
|
+
requires :a, types: [Grape::API::Boolean, String], coerce_with: (lambda do |val|
|
1204
|
+
case val
|
1205
|
+
when 'yup'
|
1101
1206
|
true
|
1102
|
-
|
1207
|
+
when 'false'
|
1103
1208
|
0
|
1104
1209
|
else
|
1105
1210
|
val
|
@@ -2,104 +2,98 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
describe Grape::Validations::DefaultValidator do
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
5
|
+
describe Grape::Validations::Validators::DefaultValidator do
|
6
|
+
let_it_be(:app) do
|
7
|
+
Class.new(Grape::API) do
|
8
|
+
default_format :json
|
9
|
+
|
10
|
+
params do
|
11
|
+
optional :id
|
12
|
+
optional :type, default: 'default-type'
|
13
|
+
end
|
14
|
+
get '/' do
|
15
|
+
{ id: params[:id], type: params[:type] }
|
16
|
+
end
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
18
|
+
params do
|
19
|
+
optional :type1, default: 'default-type1'
|
20
|
+
optional :type2, default: 'default-type2'
|
21
|
+
end
|
22
|
+
get '/user' do
|
23
|
+
{ type1: params[:type1], type2: params[:type2] }
|
24
|
+
end
|
26
25
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
26
|
+
params do
|
27
|
+
requires :id
|
28
|
+
optional :type1, default: 'default-type1'
|
29
|
+
optional :type2, default: 'default-type2'
|
30
|
+
end
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
|
32
|
+
get '/message' do
|
33
|
+
{ id: params[:id], type1: params[:type1], type2: params[:type2] }
|
34
|
+
end
|
36
35
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
36
|
+
params do
|
37
|
+
optional :random, default: -> { Random.rand }
|
38
|
+
optional :not_random, default: Random.rand
|
39
|
+
end
|
40
|
+
get '/numbers' do
|
41
|
+
{ random_number: params[:random], non_random_number: params[:non_random_number] }
|
42
|
+
end
|
44
43
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
50
|
-
end
|
51
|
-
get '/array' do
|
52
|
-
{ array: params[:array] }
|
44
|
+
params do
|
45
|
+
optional :array, type: Array do
|
46
|
+
requires :name
|
47
|
+
optional :with_default, default: 'default'
|
53
48
|
end
|
49
|
+
end
|
50
|
+
get '/array' do
|
51
|
+
{ array: params[:array] }
|
52
|
+
end
|
54
53
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
end
|
61
|
-
end
|
62
|
-
get '/optional_array' do
|
63
|
-
{ thing1: params[:thing1] }
|
54
|
+
params do
|
55
|
+
requires :thing1
|
56
|
+
optional :more_things, type: Array do
|
57
|
+
requires :nested_thing
|
58
|
+
requires :other_thing, default: 1
|
64
59
|
end
|
60
|
+
end
|
61
|
+
get '/optional_array' do
|
62
|
+
{ thing1: params[:thing1] }
|
63
|
+
end
|
65
64
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
end
|
65
|
+
params do
|
66
|
+
requires :root, type: Hash do
|
67
|
+
optional :some_things, type: Array do
|
68
|
+
requires :foo
|
69
|
+
optional :options, type: Array do
|
70
|
+
requires :name, type: String
|
71
|
+
requires :value, type: String
|
74
72
|
end
|
75
73
|
end
|
76
74
|
end
|
77
|
-
|
78
|
-
|
79
|
-
|
75
|
+
end
|
76
|
+
get '/nested_optional_array' do
|
77
|
+
{ root: params[:root] }
|
78
|
+
end
|
80
79
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
end
|
80
|
+
params do
|
81
|
+
requires :root, type: Hash do
|
82
|
+
optional :some_things, type: Array do
|
83
|
+
requires :foo
|
84
|
+
optional :options, type: Array do
|
85
|
+
optional :name, type: String
|
86
|
+
optional :value, type: String
|
89
87
|
end
|
90
88
|
end
|
91
89
|
end
|
92
|
-
|
93
|
-
|
94
|
-
|
90
|
+
end
|
91
|
+
get '/another_nested_optional_array' do
|
92
|
+
{ root: params[:root] }
|
95
93
|
end
|
96
94
|
end
|
97
95
|
end
|
98
96
|
|
99
|
-
def app
|
100
|
-
ValidationsSpec::DefaultValidatorSpec::API
|
101
|
-
end
|
102
|
-
|
103
97
|
it 'lets you leave required values nested inside an optional blank' do
|
104
98
|
get '/optional_array', thing1: 'stuff'
|
105
99
|
expect(last_response.status).to eq(200)
|