grape 1.5.3 → 1.6.2
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 +39 -0
- data/CONTRIBUTING.md +2 -1
- data/README.md +31 -3
- data/UPGRADING.md +46 -4
- data/grape.gemspec +5 -5
- data/lib/grape/api/instance.rb +13 -17
- data/lib/grape/api.rb +17 -12
- data/lib/grape/cookies.rb +2 -0
- 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 +17 -8
- data/lib/grape/dsl/middleware.rb +4 -4
- data/lib/grape/dsl/parameters.rb +3 -3
- data/lib/grape/dsl/request_response.rb +9 -6
- data/lib/grape/dsl/routing.rb +2 -2
- data/lib/grape/dsl/settings.rb +5 -5
- data/lib/grape/endpoint.rb +20 -35
- data/lib/grape/error_formatter/json.rb +2 -6
- data/lib/grape/error_formatter/xml.rb +2 -6
- data/lib/grape/exceptions/validation.rb +1 -2
- 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/middleware/auth/dsl.rb +7 -1
- data/lib/grape/middleware/base.rb +3 -1
- data/lib/grape/middleware/formatter.rb +4 -4
- data/lib/grape/middleware/stack.rb +2 -2
- 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/path.rb +1 -0
- data/lib/grape/request.rb +1 -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/lazy_value.rb +3 -2
- data/lib/grape/util/strict_hash_configuration.rb +1 -1
- data/lib/grape/validations/params_scope.rb +88 -55
- data/lib/grape/validations/types/custom_type_coercer.rb +1 -0
- data/lib/grape/validations/types/dry_type_coercer.rb +1 -1
- data/lib/grape/validations/types/json.rb +2 -1
- data/lib/grape/validations/types/primitive_coercer.rb +3 -3
- data/lib/grape/validations/validators/all_or_none.rb +8 -5
- data/lib/grape/validations/validators/allow_blank.rb +9 -7
- data/lib/grape/validations/validators/as.rb +6 -8
- data/lib/grape/validations/validators/at_least_one_of.rb +7 -4
- data/lib/grape/validations/validators/base.rb +75 -70
- data/lib/grape/validations/validators/coerce.rb +63 -79
- data/lib/grape/validations/validators/default.rb +37 -34
- data/lib/grape/validations/validators/exactly_one_of.rb +9 -6
- data/lib/grape/validations/validators/except_values.rb +13 -11
- data/lib/grape/validations/validators/multiple_params_base.rb +24 -20
- data/lib/grape/validations/validators/mutual_exclusion.rb +8 -5
- data/lib/grape/validations/validators/presence.rb +7 -4
- data/lib/grape/validations/validators/regexp.rb +8 -5
- data/lib/grape/validations/validators/same_as.rb +18 -15
- data/lib/grape/validations/validators/values.rb +61 -56
- data/lib/grape/validations.rb +6 -0
- data/lib/grape/version.rb +1 -1
- data/lib/grape.rb +3 -1
- 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 +16 -15
- data/spec/grape/api_spec.rb +440 -227
- 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 +64 -55
- data/spec/grape/entity_spec.rb +22 -22
- 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 +14 -12
- 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 +23 -22
- 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 +12 -9
- data/spec/spec_helper.rb +12 -2
- data/spec/support/basic_auth_encode_helpers.rb +1 -1
- metadata +103 -103
@@ -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]
|
@@ -369,9 +370,9 @@ describe Grape::Validations::CoerceValidator do
|
|
369
370
|
end
|
370
371
|
end
|
371
372
|
|
372
|
-
it 'Boolean' do
|
373
|
+
it 'Grape::API::Boolean' do
|
373
374
|
subject.params do
|
374
|
-
requires :boolean, type: Boolean
|
375
|
+
requires :boolean, type: Grape::API::Boolean
|
375
376
|
end
|
376
377
|
subject.get '/boolean' do
|
377
378
|
params[:boolean].class
|
@@ -650,7 +651,7 @@ describe Grape::Validations::CoerceValidator do
|
|
650
651
|
|
651
652
|
it 'parses parameters with Array[Array[String]] type and coerce_with' do
|
652
653
|
subject.params do
|
653
|
-
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 }
|
654
655
|
end
|
655
656
|
subject.post '/coerce_nested_strings' do
|
656
657
|
params[:values]
|
@@ -834,9 +835,10 @@ describe Grape::Validations::CoerceValidator do
|
|
834
835
|
before do
|
835
836
|
subject.params do
|
836
837
|
requires :int, type: Integer, coerce_with: (lambda do |val|
|
837
|
-
|
838
|
+
case val
|
839
|
+
when '0'
|
838
840
|
nil
|
839
|
-
|
841
|
+
when /^-?\d+$/
|
840
842
|
val.to_i
|
841
843
|
else
|
842
844
|
val
|
@@ -1016,11 +1018,9 @@ describe Grape::Validations::CoerceValidator do
|
|
1016
1018
|
end
|
1017
1019
|
|
1018
1020
|
context 'multiple types' do
|
1019
|
-
Boolean = Grape::API::Boolean
|
1020
|
-
|
1021
1021
|
it 'coerces to first possible type' do
|
1022
1022
|
subject.params do
|
1023
|
-
requires :a, types: [Boolean, Integer, String]
|
1023
|
+
requires :a, types: [Grape::API::Boolean, Integer, String]
|
1024
1024
|
end
|
1025
1025
|
subject.get '/' do
|
1026
1026
|
params[:a].class.to_s
|
@@ -1041,7 +1041,7 @@ describe Grape::Validations::CoerceValidator do
|
|
1041
1041
|
|
1042
1042
|
it 'fails when no coercion is possible' do
|
1043
1043
|
subject.params do
|
1044
|
-
requires :a, types: [Boolean, Integer]
|
1044
|
+
requires :a, types: [Grape::API::Boolean, Integer]
|
1045
1045
|
end
|
1046
1046
|
subject.get '/' do
|
1047
1047
|
params[:a].class.to_s
|
@@ -1200,10 +1200,11 @@ describe Grape::Validations::CoerceValidator do
|
|
1200
1200
|
context 'custom coercion rules' do
|
1201
1201
|
before do
|
1202
1202
|
subject.params do
|
1203
|
-
requires :a, types: [Boolean, String], coerce_with: (lambda do |val|
|
1204
|
-
|
1203
|
+
requires :a, types: [Grape::API::Boolean, String], coerce_with: (lambda do |val|
|
1204
|
+
case val
|
1205
|
+
when 'yup'
|
1205
1206
|
true
|
1206
|
-
|
1207
|
+
when 'false'
|
1207
1208
|
0
|
1208
1209
|
else
|
1209
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)
|
@@ -2,95 +2,89 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
describe Grape::Validations::ExactlyOneOfValidator 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::ExactlyOneOfValidator 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
|
-
|
22
|
-
|
23
|
-
|
12
|
+
params do
|
13
|
+
optional :beer
|
14
|
+
optional :wine
|
15
|
+
optional :grapefruit
|
16
|
+
exactly_one_of :beer, :wine, :grapefruit
|
17
|
+
end
|
18
|
+
post do
|
19
|
+
end
|
24
20
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
21
|
+
params do
|
22
|
+
optional :beer
|
23
|
+
optional :wine
|
24
|
+
optional :grapefruit
|
25
|
+
optional :other
|
26
|
+
exactly_one_of :beer, :wine, :grapefruit
|
27
|
+
end
|
28
|
+
post 'mixed-params' do
|
29
|
+
end
|
34
30
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
31
|
+
params do
|
32
|
+
optional :beer
|
33
|
+
optional :wine
|
34
|
+
optional :grapefruit
|
35
|
+
exactly_one_of :beer, :wine, :grapefruit, message: 'you should choose one'
|
36
|
+
end
|
37
|
+
post '/custom-message' do
|
38
|
+
end
|
43
39
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
40
|
+
params do
|
41
|
+
requires :item, type: Hash do
|
42
|
+
optional :beer
|
43
|
+
optional :wine
|
44
|
+
optional :grapefruit
|
45
|
+
exactly_one_of :beer, :wine, :grapefruit
|
46
|
+
end
|
47
|
+
end
|
48
|
+
post '/nested-hash' do
|
49
|
+
end
|
54
50
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
51
|
+
params do
|
52
|
+
optional :item, type: Hash do
|
53
|
+
optional :beer
|
54
|
+
optional :wine
|
55
|
+
optional :grapefruit
|
56
|
+
exactly_one_of :beer, :wine, :grapefruit
|
57
|
+
end
|
58
|
+
end
|
59
|
+
post '/nested-optional-hash' do
|
60
|
+
end
|
65
61
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
62
|
+
params do
|
63
|
+
requires :items, type: Array do
|
64
|
+
optional :beer
|
65
|
+
optional :wine
|
66
|
+
optional :grapefruit
|
67
|
+
exactly_one_of :beer, :wine, :grapefruit
|
68
|
+
end
|
69
|
+
end
|
70
|
+
post '/nested-array' do
|
71
|
+
end
|
76
72
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
post '/deeply-nested-array' do
|
73
|
+
params do
|
74
|
+
requires :items, type: Array do
|
75
|
+
requires :nested_items, type: Array do
|
76
|
+
optional :beer, :wine, :grapefruit, type: Grape::API::Boolean
|
77
|
+
exactly_one_of :beer, :wine, :grapefruit
|
86
78
|
end
|
87
79
|
end
|
88
80
|
end
|
81
|
+
post '/deeply-nested-array' do
|
82
|
+
end
|
89
83
|
end
|
84
|
+
end
|
90
85
|
|
91
|
-
|
92
|
-
|
93
|
-
end
|
86
|
+
describe '#validate!' do
|
87
|
+
subject(:validate) { post path, params }
|
94
88
|
|
95
89
|
context 'when all params are present' do
|
96
90
|
let(:path) { '/' }
|
@@ -2,10 +2,10 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
describe Grape::Validations::ExceptValuesValidator do
|
5
|
+
describe Grape::Validations::Validators::ExceptValuesValidator do
|
6
6
|
module ValidationsSpec
|
7
7
|
class ExceptValuesModel
|
8
|
-
DEFAULT_EXCEPTS = [
|
8
|
+
DEFAULT_EXCEPTS = %w[invalid-type1 invalid-type2 invalid-type3].freeze
|
9
9
|
class << self
|
10
10
|
attr_accessor :excepts
|
11
11
|
|
@@ -170,7 +170,7 @@ describe Grape::Validations::ExceptValuesValidator do
|
|
170
170
|
it 'raises IncompatibleOptionValues when type is incompatible with values array' do
|
171
171
|
subject = Class.new(Grape::API)
|
172
172
|
expect do
|
173
|
-
subject.params { optional :type, except_values: [
|
173
|
+
subject.params { optional :type, except_values: %w[valid-type1 valid-type2 valid-type3], type: Symbol }
|
174
174
|
end.to raise_error Grape::Exceptions::IncompatibleOptionValues
|
175
175
|
end
|
176
176
|
|