grape 1.5.3 → 1.6.0
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 +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
|
- - ">="
|