grape 1.5.3 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/README.md +23 -3
- data/UPGRADING.md +43 -1
- data/grape.gemspec +5 -5
- data/lib/grape/api/instance.rb +13 -17
- data/lib/grape/api.rb +5 -12
- data/lib/grape/cookies.rb +2 -0
- data/lib/grape/dsl/desc.rb +3 -5
- data/lib/grape/dsl/helpers.rb +6 -4
- 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/base.rb +2 -0
- 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/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 +1 -0
- data/lib/grape/validations/validators/as.rb +4 -8
- data/lib/grape/validations/validators/at_least_one_of.rb +1 -0
- data/lib/grape/validations/validators/base.rb +4 -1
- data/lib/grape/validations/validators/coerce.rb +1 -5
- data/lib/grape/validations/validators/default.rb +1 -0
- data/lib/grape/validations/validators/exactly_one_of.rb +1 -0
- data/lib/grape/validations/validators/multiple_params_base.rb +2 -0
- data/lib/grape/validations/validators/mutual_exclusion.rb +1 -0
- data/lib/grape/validations/validators/presence.rb +1 -0
- data/lib/grape/validations/validators/regexp.rb +1 -0
- data/lib/grape/validations/validators/same_as.rb +1 -0
- data/lib/grape/validations/validators/values.rb +3 -0
- data/lib/grape/version.rb +1 -1
- data/lib/grape.rb +1 -1
- data/spec/grape/api/custom_validations_spec.rb +1 -0
- data/spec/grape/api/routes_with_requirements_spec.rb +8 -8
- data/spec/grape/api_spec.rb +126 -37
- data/spec/grape/dsl/callbacks_spec.rb +1 -1
- data/spec/grape/dsl/middleware_spec.rb +1 -1
- data/spec/grape/dsl/parameters_spec.rb +1 -0
- data/spec/grape/dsl/routing_spec.rb +1 -1
- data/spec/grape/endpoint/declared_spec.rb +247 -0
- data/spec/grape/endpoint_spec.rb +5 -5
- data/spec/grape/entity_spec.rb +9 -9
- data/spec/grape/middleware/auth/dsl_spec.rb +1 -1
- data/spec/grape/middleware/error_spec.rb +1 -2
- data/spec/grape/middleware/formatter_spec.rb +2 -2
- data/spec/grape/middleware/stack_spec.rb +3 -1
- data/spec/grape/validations/params_scope_spec.rb +37 -3
- data/spec/grape/validations/single_attribute_iterator_spec.rb +1 -1
- data/spec/grape/validations/types/primitive_coercer_spec.rb +2 -2
- data/spec/grape/validations/validators/coerce_spec.rb +13 -10
- data/spec/grape/validations/validators/except_values_spec.rb +2 -2
- data/spec/grape/validations/validators/values_spec.rb +15 -11
- data/spec/grape/validations_spec.rb +54 -42
- data/spec/shared/versioning_examples.rb +2 -2
- data/spec/spec_helper.rb +1 -1
- data/spec/support/basic_auth_encode_helpers.rb +1 -1
- metadata +6 -6
@@ -98,6 +98,7 @@ describe Grape::Validations::ParamsScope do
|
|
98
98
|
|
99
99
|
def self.parse(value)
|
100
100
|
raise if value == 'invalid'
|
101
|
+
|
101
102
|
new(value)
|
102
103
|
end
|
103
104
|
|
@@ -144,7 +145,7 @@ describe Grape::Validations::ParamsScope do
|
|
144
145
|
get '/renaming-coerced', foo: ' there we go '
|
145
146
|
|
146
147
|
expect(last_response.status).to eq(200)
|
147
|
-
expect(last_response.body).to eq('there we go
|
148
|
+
expect(last_response.body).to eq('-there we go')
|
148
149
|
end
|
149
150
|
|
150
151
|
it do
|
@@ -180,6 +181,28 @@ describe Grape::Validations::ParamsScope do
|
|
180
181
|
expect(last_response.status).to eq(200)
|
181
182
|
expect(last_response.body).to eq('{"baz":{"qux":"any"}}')
|
182
183
|
end
|
184
|
+
|
185
|
+
it 'renaming can be defined before default' do
|
186
|
+
subject.params do
|
187
|
+
optional :foo, as: :bar, default: 'before'
|
188
|
+
end
|
189
|
+
subject.get('/rename-before-default') { declared(params)[:bar] }
|
190
|
+
get '/rename-before-default'
|
191
|
+
|
192
|
+
expect(last_response.status).to eq(200)
|
193
|
+
expect(last_response.body).to eq('before')
|
194
|
+
end
|
195
|
+
|
196
|
+
it 'renaming can be defined after default' do
|
197
|
+
subject.params do
|
198
|
+
optional :foo, default: 'after', as: :bar
|
199
|
+
end
|
200
|
+
subject.get('/rename-after-default') { declared(params)[:bar] }
|
201
|
+
get '/rename-after-default'
|
202
|
+
|
203
|
+
expect(last_response.status).to eq(200)
|
204
|
+
expect(last_response.body).to eq('after')
|
205
|
+
end
|
183
206
|
end
|
184
207
|
|
185
208
|
context 'array without coerce type explicitly given' do
|
@@ -568,7 +591,7 @@ describe Grape::Validations::ParamsScope do
|
|
568
591
|
it 'allows renaming of dependent on parameter' do
|
569
592
|
subject.params do
|
570
593
|
optional :a, as: :b
|
571
|
-
given
|
594
|
+
given a: ->(val) { val == 'x' } do
|
572
595
|
requires :c
|
573
596
|
end
|
574
597
|
end
|
@@ -582,7 +605,7 @@ describe Grape::Validations::ParamsScope do
|
|
582
605
|
expect(last_response.status).to eq 200
|
583
606
|
end
|
584
607
|
|
585
|
-
it '
|
608
|
+
it 'does not raise if the dependent parameter is not the renamed one' do
|
586
609
|
expect do
|
587
610
|
subject.params do
|
588
611
|
optional :a, as: :b
|
@@ -590,6 +613,17 @@ describe Grape::Validations::ParamsScope do
|
|
590
613
|
requires :c
|
591
614
|
end
|
592
615
|
end
|
616
|
+
end.not_to raise_error
|
617
|
+
end
|
618
|
+
|
619
|
+
it 'raises an error if the dependent parameter is the renamed one' do
|
620
|
+
expect do
|
621
|
+
subject.params do
|
622
|
+
optional :a, as: :b
|
623
|
+
given :b do
|
624
|
+
requires :c
|
625
|
+
end
|
626
|
+
end
|
593
627
|
end.to raise_error(Grape::Exceptions::UnknownParameter)
|
594
628
|
end
|
595
629
|
|
@@ -49,7 +49,7 @@ describe Grape::Validations::SingleAttributeIterator do
|
|
49
49
|
it 'marks params with skipped values' do
|
50
50
|
expect { |b| iterator.each(&b) }.to yield_successive_args(
|
51
51
|
[params[0], :first, false, true], [params[0], :second, false, true],
|
52
|
-
[params[1], :first, false, false], [params[1], :second, false, false]
|
52
|
+
[params[1], :first, false, false], [params[1], :second, false, false]
|
53
53
|
)
|
54
54
|
end
|
55
55
|
end
|
@@ -12,7 +12,7 @@ describe Grape::Validations::Types::PrimitiveCoercer do
|
|
12
12
|
let(:type) { BigDecimal }
|
13
13
|
|
14
14
|
it 'coerces to BigDecimal' do
|
15
|
-
expect(subject.call(5)).to eq(BigDecimal(5))
|
15
|
+
expect(subject.call(5)).to eq(BigDecimal('5'))
|
16
16
|
end
|
17
17
|
|
18
18
|
it 'coerces an empty string to nil' do
|
@@ -127,7 +127,7 @@ describe Grape::Validations::Types::PrimitiveCoercer do
|
|
127
127
|
end
|
128
128
|
|
129
129
|
it 'returns a value as it is when the given value is BigDecimal' do
|
130
|
-
expect(subject.call(BigDecimal(0))).to eq(BigDecimal(0))
|
130
|
+
expect(subject.call(BigDecimal('0'))).to eq(BigDecimal('0'))
|
131
131
|
end
|
132
132
|
end
|
133
133
|
end
|
@@ -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
|
@@ -84,9 +84,10 @@ describe Grape::Validations::CoerceValidator do
|
|
84
84
|
before do
|
85
85
|
subject.params do
|
86
86
|
requires :a, types: { value: [Boolean, String], message: 'type cast is invalid' }, coerce_with: (lambda do |val|
|
87
|
-
|
87
|
+
case val
|
88
|
+
when 'yup'
|
88
89
|
true
|
89
|
-
|
90
|
+
when 'false'
|
90
91
|
0
|
91
92
|
else
|
92
93
|
val
|
@@ -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
|
@@ -1201,9 +1203,10 @@ describe Grape::Validations::CoerceValidator do
|
|
1201
1203
|
before do
|
1202
1204
|
subject.params do
|
1203
1205
|
requires :a, types: [Boolean, String], coerce_with: (lambda do |val|
|
1204
|
-
|
1206
|
+
case val
|
1207
|
+
when 'yup'
|
1205
1208
|
true
|
1206
|
-
|
1209
|
+
when 'false'
|
1207
1210
|
0
|
1208
1211
|
else
|
1209
1212
|
val
|
@@ -5,7 +5,7 @@ require 'spec_helper'
|
|
5
5
|
describe Grape::Validations::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
|
|
@@ -5,8 +5,8 @@ require 'spec_helper'
|
|
5
5
|
describe Grape::Validations::ValuesValidator do
|
6
6
|
module ValidationsSpec
|
7
7
|
class ValuesModel
|
8
|
-
DEFAULT_VALUES = [
|
9
|
-
DEFAULT_EXCEPTS = [
|
8
|
+
DEFAULT_VALUES = %w[valid-type1 valid-type2 valid-type3].freeze
|
9
|
+
DEFAULT_EXCEPTS = %w[invalid-type1 invalid-type2 invalid-type3].freeze
|
10
10
|
class << self
|
11
11
|
def values
|
12
12
|
@values ||= []
|
@@ -27,6 +27,10 @@ describe Grape::Validations::ValuesValidator do
|
|
27
27
|
@excepts ||= []
|
28
28
|
@excepts << except
|
29
29
|
end
|
30
|
+
|
31
|
+
def include?(value)
|
32
|
+
values.include?(value)
|
33
|
+
end
|
30
34
|
end
|
31
35
|
end
|
32
36
|
|
@@ -106,7 +110,7 @@ describe Grape::Validations::ValuesValidator do
|
|
106
110
|
end
|
107
111
|
|
108
112
|
params do
|
109
|
-
requires :type, values: ->(v) { ValuesModel.
|
113
|
+
requires :type, values: ->(v) { ValuesModel.include? v }
|
110
114
|
end
|
111
115
|
get '/lambda_val' do
|
112
116
|
{ type: params[:type] }
|
@@ -214,14 +218,14 @@ describe Grape::Validations::ValuesValidator do
|
|
214
218
|
put '/optional_with_array_of_string_values'
|
215
219
|
|
216
220
|
params do
|
217
|
-
requires :type, values: { proc: ->(v) { ValuesModel.
|
221
|
+
requires :type, values: { proc: ->(v) { ValuesModel.include? v } }
|
218
222
|
end
|
219
223
|
get '/proc' do
|
220
224
|
{ type: params[:type] }
|
221
225
|
end
|
222
226
|
|
223
227
|
params do
|
224
|
-
requires :type, values: { proc: ->(v) { ValuesModel.
|
228
|
+
requires :type, values: { proc: ->(v) { ValuesModel.include? v }, message: 'failed check' }
|
225
229
|
end
|
226
230
|
get '/proc/message'
|
227
231
|
|
@@ -420,21 +424,21 @@ describe Grape::Validations::ValuesValidator do
|
|
420
424
|
it 'raises IncompatibleOptionValues on an invalid default value from proc' do
|
421
425
|
subject = Class.new(Grape::API)
|
422
426
|
expect do
|
423
|
-
subject.params { optional :type, values: [
|
427
|
+
subject.params { optional :type, values: %w[valid-type1 valid-type2 valid-type3], default: "#{ValidationsSpec::ValuesModel.values.sample}_invalid" }
|
424
428
|
end.to raise_error Grape::Exceptions::IncompatibleOptionValues
|
425
429
|
end
|
426
430
|
|
427
431
|
it 'raises IncompatibleOptionValues on an invalid default value' do
|
428
432
|
subject = Class.new(Grape::API)
|
429
433
|
expect do
|
430
|
-
subject.params { optional :type, values: [
|
434
|
+
subject.params { optional :type, values: %w[valid-type1 valid-type2 valid-type3], default: 'invalid-type' }
|
431
435
|
end.to raise_error Grape::Exceptions::IncompatibleOptionValues
|
432
436
|
end
|
433
437
|
|
434
438
|
it 'raises IncompatibleOptionValues when type is incompatible with values array' do
|
435
439
|
subject = Class.new(Grape::API)
|
436
440
|
expect do
|
437
|
-
subject.params { optional :type, values: [
|
441
|
+
subject.params { optional :type, values: %w[valid-type1 valid-type2 valid-type3], type: Symbol }
|
438
442
|
end.to raise_error Grape::Exceptions::IncompatibleOptionValues
|
439
443
|
end
|
440
444
|
|
@@ -648,9 +652,9 @@ describe Grape::Validations::ValuesValidator do
|
|
648
652
|
end
|
649
653
|
|
650
654
|
it 'accepts multiple valid values' do
|
651
|
-
get '/proc', type: [
|
655
|
+
get '/proc', type: %w[valid-type1 valid-type3]
|
652
656
|
expect(last_response.status).to eq 200
|
653
|
-
expect(last_response.body).to eq({ type: [
|
657
|
+
expect(last_response.body).to eq({ type: %w[valid-type1 valid-type3] }.to_json)
|
654
658
|
end
|
655
659
|
|
656
660
|
it 'rejects a single invalid value' do
|
@@ -660,7 +664,7 @@ describe Grape::Validations::ValuesValidator do
|
|
660
664
|
end
|
661
665
|
|
662
666
|
it 'rejects an invalid value among valid ones' do
|
663
|
-
get '/proc', type: [
|
667
|
+
get '/proc', type: %w[valid-type1 invalid-type1 valid-type3]
|
664
668
|
expect(last_response.status).to eq 400
|
665
669
|
expect(last_response.body).to eq({ error: 'type does not have a valid value' }.to_json)
|
666
670
|
end
|
@@ -494,6 +494,7 @@ describe Grape::Validations do
|
|
494
494
|
class DateRangeValidator < Grape::Validations::Base
|
495
495
|
def validate_param!(attr_name, params)
|
496
496
|
return if params[attr_name][:from] <= params[attr_name][:to]
|
497
|
+
|
497
498
|
raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: "'from' must be lower or equal to 'to'")
|
498
499
|
end
|
499
500
|
end
|
@@ -887,13 +888,13 @@ describe Grape::Validations do
|
|
887
888
|
context <<~DESC do
|
888
889
|
Issue occurs whenever:
|
889
890
|
* param structure with at least three levels
|
890
|
-
* 1st level item is a required Array that has >1 entry with an optional item present and >1 entry with an optional item missing
|
891
|
-
* 2nd level is an optional Array or Hash
|
891
|
+
* 1st level item is a required Array that has >1 entry with an optional item present and >1 entry with an optional item missing#{' '}
|
892
|
+
* 2nd level is an optional Array or Hash#{' '}
|
892
893
|
* 3rd level is a required item (can be any type)
|
893
894
|
* additional levels do not effect the issue from occuring
|
894
895
|
DESC
|
895
896
|
|
896
|
-
it
|
897
|
+
it 'example based off actual real world use case' do
|
897
898
|
subject.params do
|
898
899
|
requires :orders, type: Array do
|
899
900
|
requires :id, type: Integer
|
@@ -911,17 +912,17 @@ describe Grape::Validations do
|
|
911
912
|
|
912
913
|
data = {
|
913
914
|
orders: [
|
914
|
-
{ id: 77, drugs: [{batches: [{batch_no:
|
915
|
+
{ id: 77, drugs: [{ batches: [{ batch_no: 'A1234567' }] }] },
|
915
916
|
{ id: 70 }
|
916
917
|
]
|
917
918
|
}
|
918
919
|
|
919
920
|
get '/validate_required_arrays_under_optional_arrays', data
|
920
|
-
expect(last_response.body).to eq(
|
921
|
+
expect(last_response.body).to eq('validate_required_arrays_under_optional_arrays works!')
|
921
922
|
expect(last_response.status).to eq(200)
|
922
923
|
end
|
923
924
|
|
924
|
-
it
|
925
|
+
it 'simplest example using Array -> Array -> Hash -> String' do
|
925
926
|
subject.params do
|
926
927
|
requires :orders, type: Array do
|
927
928
|
requires :id, type: Integer
|
@@ -937,17 +938,17 @@ describe Grape::Validations do
|
|
937
938
|
|
938
939
|
data = {
|
939
940
|
orders: [
|
940
|
-
{ id: 77, drugs: [{batch_no:
|
941
|
+
{ id: 77, drugs: [{ batch_no: 'A1234567' }] },
|
941
942
|
{ id: 70 }
|
942
943
|
]
|
943
944
|
}
|
944
945
|
|
945
946
|
get '/validate_required_arrays_under_optional_arrays', data
|
946
|
-
expect(last_response.body).to eq(
|
947
|
+
expect(last_response.body).to eq('validate_required_arrays_under_optional_arrays works!')
|
947
948
|
expect(last_response.status).to eq(200)
|
948
949
|
end
|
949
950
|
|
950
|
-
it
|
951
|
+
it 'simplest example using Array -> Hash -> String' do
|
951
952
|
subject.params do
|
952
953
|
requires :orders, type: Array do
|
953
954
|
requires :id, type: Integer
|
@@ -963,17 +964,17 @@ describe Grape::Validations do
|
|
963
964
|
|
964
965
|
data = {
|
965
966
|
orders: [
|
966
|
-
{ id: 77, drugs: {batch_no:
|
967
|
+
{ id: 77, drugs: { batch_no: 'A1234567' } },
|
967
968
|
{ id: 70 }
|
968
969
|
]
|
969
970
|
}
|
970
971
|
|
971
972
|
get '/validate_required_arrays_under_optional_arrays', data
|
972
|
-
expect(last_response.body).to eq(
|
973
|
+
expect(last_response.body).to eq('validate_required_arrays_under_optional_arrays works!')
|
973
974
|
expect(last_response.status).to eq(200)
|
974
975
|
end
|
975
976
|
|
976
|
-
it
|
977
|
+
it 'correctly indexes invalida data' do
|
977
978
|
subject.params do
|
978
979
|
requires :orders, type: Array do
|
979
980
|
requires :id, type: Integer
|
@@ -991,16 +992,16 @@ describe Grape::Validations do
|
|
991
992
|
data = {
|
992
993
|
orders: [
|
993
994
|
{ id: 70 },
|
994
|
-
{ id: 77, drugs: [{batch_no:
|
995
|
+
{ id: 77, drugs: [{ batch_no: 'A1234567', quantity: 12 }, { batch_no: 'B222222' }] }
|
995
996
|
]
|
996
997
|
}
|
997
998
|
|
998
999
|
get '/correctly_indexes', data
|
999
|
-
expect(last_response.body).to eq(
|
1000
|
+
expect(last_response.body).to eq('orders[1][drugs][1][quantity] is missing')
|
1000
1001
|
expect(last_response.status).to eq(400)
|
1001
1002
|
end
|
1002
1003
|
|
1003
|
-
context
|
1004
|
+
context 'multiple levels of optional and requires settings' do
|
1004
1005
|
before do
|
1005
1006
|
subject.params do
|
1006
1007
|
requires :top, type: Array do
|
@@ -1022,53 +1023,62 @@ describe Grape::Validations do
|
|
1022
1023
|
end
|
1023
1024
|
end
|
1024
1025
|
|
1025
|
-
it
|
1026
|
+
it 'with valid data' do
|
1026
1027
|
data = {
|
1027
1028
|
top: [
|
1028
1029
|
{ top_id: 1, middle_1: [
|
1029
|
-
{middle_1_id: 11}, {middle_1_id: 12, middle_2: [
|
1030
|
-
{middle_2_id: 121}, {middle_2_id: 122, bottom: [{bottom_id: 1221}]}
|
1030
|
+
{ middle_1_id: 11 }, { middle_1_id: 12, middle_2: [
|
1031
|
+
{ middle_2_id: 121 }, { middle_2_id: 122, bottom: [{ bottom_id: 1221 }] }
|
1032
|
+
] }
|
1033
|
+
] },
|
1031
1034
|
{ top_id: 2, middle_1: [
|
1032
|
-
{middle_1_id: 21}, {middle_1_id: 22, middle_2: [
|
1033
|
-
|
1035
|
+
{ middle_1_id: 21 }, { middle_1_id: 22, middle_2: [
|
1036
|
+
{ middle_2_id: 221 }
|
1037
|
+
] }
|
1038
|
+
] },
|
1034
1039
|
{ top_id: 3, middle_1: [
|
1035
|
-
{middle_1_id: 31}, {middle_1_id: 32}
|
1040
|
+
{ middle_1_id: 31 }, { middle_1_id: 32 }
|
1041
|
+
] },
|
1036
1042
|
{ top_id: 4 }
|
1037
1043
|
]
|
1038
1044
|
}
|
1039
1045
|
|
1040
1046
|
get '/multi_level', data
|
1041
|
-
expect(last_response.body).to eq(
|
1047
|
+
expect(last_response.body).to eq('multi_level works!')
|
1042
1048
|
expect(last_response.status).to eq(200)
|
1043
1049
|
end
|
1044
1050
|
|
1045
|
-
it
|
1051
|
+
it 'with invalid data' do
|
1046
1052
|
data = {
|
1047
1053
|
top: [
|
1048
1054
|
{ top_id: 1, middle_1: [
|
1049
|
-
{middle_1_id: 11}, {middle_1_id: 12, middle_2: [
|
1050
|
-
|
1055
|
+
{ middle_1_id: 11 }, { middle_1_id: 12, middle_2: [
|
1056
|
+
{ middle_2_id: 121 }, { middle_2_id: 122, bottom: [{ bottom_id: nil }] }
|
1057
|
+
] }
|
1058
|
+
] },
|
1051
1059
|
{ top_id: 2, middle_1: [
|
1052
|
-
{middle_1_id: 21}, {middle_1_id: 22, middle_2: [{middle_2_id: nil}]}
|
1060
|
+
{ middle_1_id: 21 }, { middle_1_id: 22, middle_2: [{ middle_2_id: nil }] }
|
1061
|
+
] },
|
1053
1062
|
{ top_id: 3, middle_1: [
|
1054
|
-
{middle_1_id: nil}, {middle_1_id: 32}
|
1063
|
+
{ middle_1_id: nil }, { middle_1_id: 32 }
|
1064
|
+
] },
|
1055
1065
|
{ top_id: nil, missing_top_id: 4 }
|
1056
1066
|
]
|
1057
1067
|
}
|
1058
1068
|
# debugger
|
1059
1069
|
get '/multi_level', data
|
1060
|
-
expect(last_response.body.split(
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1070
|
+
expect(last_response.body.split(', ')).to match_array([
|
1071
|
+
'top[3][top_id] is empty',
|
1072
|
+
'top[2][middle_1][0][middle_1_id] is empty',
|
1073
|
+
'top[1][middle_1][1][middle_2][0][middle_2_id] is empty',
|
1074
|
+
'top[0][middle_1][1][middle_2][1][bottom][0][bottom_id] is empty'
|
1075
|
+
])
|
1066
1076
|
expect(last_response.status).to eq(400)
|
1067
1077
|
end
|
1068
1078
|
end
|
1069
1079
|
end
|
1070
1080
|
|
1071
|
-
it
|
1081
|
+
it 'exactly_one_of' do
|
1072
1082
|
subject.params do
|
1073
1083
|
requires :orders, type: Array do
|
1074
1084
|
requires :id, type: Integer
|
@@ -1086,17 +1096,17 @@ describe Grape::Validations do
|
|
1086
1096
|
|
1087
1097
|
data = {
|
1088
1098
|
orders: [
|
1089
|
-
{ id: 77, drugs: {batch_no:
|
1099
|
+
{ id: 77, drugs: { batch_no: 'A1234567' } },
|
1090
1100
|
{ id: 70 }
|
1091
1101
|
]
|
1092
1102
|
}
|
1093
1103
|
|
1094
1104
|
get '/exactly_one_of', data
|
1095
|
-
expect(last_response.body).to eq(
|
1105
|
+
expect(last_response.body).to eq('exactly_one_of works!')
|
1096
1106
|
expect(last_response.status).to eq(200)
|
1097
1107
|
end
|
1098
1108
|
|
1099
|
-
it
|
1109
|
+
it 'at_least_one_of' do
|
1100
1110
|
subject.params do
|
1101
1111
|
requires :orders, type: Array do
|
1102
1112
|
requires :id, type: Integer
|
@@ -1114,17 +1124,17 @@ describe Grape::Validations do
|
|
1114
1124
|
|
1115
1125
|
data = {
|
1116
1126
|
orders: [
|
1117
|
-
{ id: 77, drugs: {batch_no:
|
1127
|
+
{ id: 77, drugs: { batch_no: 'A1234567' } },
|
1118
1128
|
{ id: 70 }
|
1119
1129
|
]
|
1120
1130
|
}
|
1121
1131
|
|
1122
1132
|
get '/at_least_one_of', data
|
1123
|
-
expect(last_response.body).to eq(
|
1133
|
+
expect(last_response.body).to eq('at_least_one_of works!')
|
1124
1134
|
expect(last_response.status).to eq(200)
|
1125
1135
|
end
|
1126
1136
|
|
1127
|
-
it
|
1137
|
+
it 'all_or_none_of' do
|
1128
1138
|
subject.params do
|
1129
1139
|
requires :orders, type: Array do
|
1130
1140
|
requires :id, type: Integer
|
@@ -1142,13 +1152,13 @@ describe Grape::Validations do
|
|
1142
1152
|
|
1143
1153
|
data = {
|
1144
1154
|
orders: [
|
1145
|
-
{ id: 77, drugs: {batch_no:
|
1155
|
+
{ id: 77, drugs: { batch_no: 'A1234567', batch_id: '12' } },
|
1146
1156
|
{ id: 70 }
|
1147
1157
|
]
|
1148
1158
|
}
|
1149
1159
|
|
1150
1160
|
get '/all_or_none_of', data
|
1151
|
-
expect(last_response.body).to eq(
|
1161
|
+
expect(last_response.body).to eq('all_or_none_of works!')
|
1152
1162
|
expect(last_response.status).to eq(200)
|
1153
1163
|
end
|
1154
1164
|
end
|
@@ -1177,6 +1187,7 @@ describe Grape::Validations do
|
|
1177
1187
|
class Customvalidator < Grape::Validations::Base
|
1178
1188
|
def validate_param!(attr_name, params)
|
1179
1189
|
return if params[attr_name] == 'im custom'
|
1190
|
+
|
1180
1191
|
raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: 'is not custom!')
|
1181
1192
|
end
|
1182
1193
|
end
|
@@ -1325,6 +1336,7 @@ describe Grape::Validations do
|
|
1325
1336
|
class CustomvalidatorWithOptions < Grape::Validations::Base
|
1326
1337
|
def validate_param!(attr_name, params)
|
1327
1338
|
return if params[attr_name] == @option[:text]
|
1339
|
+
|
1328
1340
|
raise Grape::Exceptions::Validation.new(params: [@scope.full_name(attr_name)], message: message)
|
1329
1341
|
end
|
1330
1342
|
end
|
@@ -70,7 +70,7 @@ shared_examples_for 'versioning' do
|
|
70
70
|
|
71
71
|
subject.version 'v1', macro_options do
|
72
72
|
get 'version' do
|
73
|
-
|
73
|
+
"version #{request.env['api.version']}"
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
@@ -94,7 +94,7 @@ shared_examples_for 'versioning' do
|
|
94
94
|
|
95
95
|
subject.version 'v1', macro_options do
|
96
96
|
get 'version' do
|
97
|
-
|
97
|
+
"version #{request.env['api.version']}"
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: grape
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Bleigh
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-10-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -371,9 +371,9 @@ licenses:
|
|
371
371
|
- MIT
|
372
372
|
metadata:
|
373
373
|
bug_tracker_uri: https://github.com/ruby-grape/grape/issues
|
374
|
-
changelog_uri: https://github.com/ruby-grape/grape/blob/v1.
|
375
|
-
documentation_uri: https://www.rubydoc.info/gems/grape/1.
|
376
|
-
source_code_uri: https://github.com/ruby-grape/grape/tree/v1.
|
374
|
+
changelog_uri: https://github.com/ruby-grape/grape/blob/v1.6.0/CHANGELOG.md
|
375
|
+
documentation_uri: https://www.rubydoc.info/gems/grape/1.6.0
|
376
|
+
source_code_uri: https://github.com/ruby-grape/grape/tree/v1.6.0
|
377
377
|
post_install_message:
|
378
378
|
rdoc_options: []
|
379
379
|
require_paths:
|
@@ -382,7 +382,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
382
382
|
requirements:
|
383
383
|
- - ">="
|
384
384
|
- !ruby/object:Gem::Version
|
385
|
-
version: 2.
|
385
|
+
version: 2.5.0
|
386
386
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
387
387
|
requirements:
|
388
388
|
- - ">="
|