grape 1.5.0 → 1.5.1
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 +3 -4
- data/UPGRADING.md +22 -0
- data/lib/grape/dsl/inside_route.rb +1 -1
- data/lib/grape/dsl/parameters.rb +7 -3
- data/lib/grape/middleware/stack.rb +4 -4
- data/lib/grape/router/attribute_translator.rb +1 -1
- data/lib/grape/validations/attributes_iterator.rb +8 -0
- data/lib/grape/validations/multiple_attributes_iterator.rb +1 -1
- data/lib/grape/validations/params_scope.rb +3 -2
- data/lib/grape/validations/single_attribute_iterator.rb +1 -1
- data/lib/grape/validations/validator_factory.rb +1 -1
- data/lib/grape/validations/validators/base.rb +2 -1
- data/lib/grape/validations/validators/multiple_params_base.rb +2 -1
- data/lib/grape/version.rb +1 -1
- data/spec/grape/endpoint/declared_spec.rb +12 -1
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +13 -3
- data/spec/grape/validations/single_attribute_iterator_spec.rb +17 -6
- data/spec/grape/validations_spec.rb +268 -0
- metadata +105 -105
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fc2b398e9ad95e7e4bb2641bbdaada929d992cd50fb551b56dbafe5f03a75589
|
4
|
+
data.tar.gz: 03765fbe9d5dafb28b531f2a454f06b2ac59d16ea28691036de797b8e64ced06
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a078c1c951ff6e5dfee34c78ab04e1f2866be316af23de469db12301ec3c86eb53bcdc9c8ac478aabe02bd3dc34f4772166e49bdf85ef731a051a8d0de73441f
|
7
|
+
data.tar.gz: 7146c097cfced8308f1efb314fb3ace44f30013af8a58a01e9a41a9aca497bd5591c060cabdcc542f25d5660b842548916282541fe869f627538ef51bb083c66
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
### 1.5.1 (2020/11/15)
|
2
|
+
|
3
|
+
#### Fixes
|
4
|
+
|
5
|
+
* Your contribution here.
|
6
|
+
* [#2129](https://github.com/ruby-grape/grape/pull/2129): Fix validation error when Required Array nested inside an optional array, for Multiparam validators - [@dwhenry](https://github.com/dwhenry).
|
7
|
+
* [#2128](https://github.com/ruby-grape/grape/pull/2128): Fix validation error when Required Array nested inside an optional array - [@dwhenry](https://github.com/dwhenry).
|
8
|
+
* [#2127](https://github.com/ruby-grape/grape/pull/2127): Fix a performance issue with dependent params - [@dnesteryuk](https://github.com/dnesteryuk).
|
9
|
+
* [#2126](https://github.com/ruby-grape/grape/pull/2126): Fix warnings about redefined attribute accessors in `AttributeTranslator` - [@samsonjs](https://github.com/samsonjs).
|
10
|
+
* [#2121](https://github.com/ruby-grape/grape/pull/2121): Fix 2.7 deprecation warning in validator_factory - [@Legogris](https://github.com/Legogris).
|
11
|
+
* [#2115](https://github.com/ruby-grape/grape/pull/2115): Fix declared_params regression with multiple allowed types - [@stanhu](https://github.com/stanhu).
|
12
|
+
* [#2123](https://github.com/ruby-grape/grape/pull/2123): Fix 2.7 deprecation warning in middleware/stack - [@Legogris](https://github.com/Legogris).
|
13
|
+
|
1
14
|
### 1.5.0 (2020/10/05)
|
2
15
|
|
3
16
|
#### Fixes
|
data/README.md
CHANGED
@@ -156,8 +156,7 @@ content negotiation, versioning and much more.
|
|
156
156
|
|
157
157
|
## Stable Release
|
158
158
|
|
159
|
-
You're reading the documentation for the stable release of Grape, 1.5.
|
160
|
-
Please read [UPGRADING](UPGRADING.md) when upgrading from a previous version.
|
159
|
+
You're reading the documentation for the stable release of Grape, 1.5.1.
|
161
160
|
|
162
161
|
## Project Resources
|
163
162
|
|
@@ -2039,10 +2038,10 @@ end
|
|
2039
2038
|
|
2040
2039
|
# is NOT the same as
|
2041
2040
|
|
2042
|
-
get ':status' do # this makes
|
2041
|
+
get ':status' do # this makes params[:status] available
|
2043
2042
|
end
|
2044
2043
|
|
2045
|
-
# This will make both
|
2044
|
+
# This will make both params[:status_id] and params[:id] available
|
2046
2045
|
|
2047
2046
|
get 'statuses/:status_id/reviews/:id' do
|
2048
2047
|
end
|
data/UPGRADING.md
CHANGED
@@ -1,6 +1,28 @@
|
|
1
1
|
Upgrading Grape
|
2
2
|
===============
|
3
3
|
|
4
|
+
### Upgrading to >= 1.5.1
|
5
|
+
|
6
|
+
#### Dependent params
|
7
|
+
|
8
|
+
If you use [dependent params](https://github.com/ruby-grape/grape#dependent-parameters) with
|
9
|
+
`Grape::Extensions::Hash::ParamBuilder`, make sure a parameter to be dependent on is set as a Symbol.
|
10
|
+
If a String is given, a parameter that other parameters depend on won't be found even if it is present.
|
11
|
+
|
12
|
+
_Correct_:
|
13
|
+
```ruby
|
14
|
+
given :matrix do
|
15
|
+
# dependent params
|
16
|
+
end
|
17
|
+
```
|
18
|
+
|
19
|
+
_Wrong_:
|
20
|
+
```ruby
|
21
|
+
given 'matrix' do
|
22
|
+
# dependent params
|
23
|
+
end
|
24
|
+
```
|
25
|
+
|
4
26
|
### Upgrading to >= 1.5.0
|
5
27
|
|
6
28
|
Prior to 1.3.3, the `declared` helper would always return the complete params structure if `include_missing=true` was set. In 1.3.3 a regression was introduced such that a missing Hash with or without nested parameters would always resolve to `{}`.
|
data/lib/grape/dsl/parameters.rb
CHANGED
@@ -227,13 +227,17 @@ module Grape
|
|
227
227
|
|
228
228
|
alias group requires
|
229
229
|
|
230
|
-
|
230
|
+
class EmptyOptionalValue; end
|
231
|
+
|
232
|
+
def map_params(params, element, is_array = false)
|
231
233
|
if params.is_a?(Array)
|
232
234
|
params.map do |el|
|
233
|
-
map_params(el, element)
|
235
|
+
map_params(el, element, true)
|
234
236
|
end
|
235
237
|
elsif params.is_a?(Hash)
|
236
|
-
params[element] || {}
|
238
|
+
params[element] || (@optional && is_array ? EmptyOptionalValue : {})
|
239
|
+
elsif params == EmptyOptionalValue
|
240
|
+
EmptyOptionalValue
|
237
241
|
else
|
238
242
|
{}
|
239
243
|
end
|
@@ -70,9 +70,9 @@ module Grape
|
|
70
70
|
middlewares[i]
|
71
71
|
end
|
72
72
|
|
73
|
-
def insert(index, *args, &block)
|
73
|
+
def insert(index, *args, **kwargs, &block)
|
74
74
|
index = assert_index(index, :before)
|
75
|
-
middleware = self.class::Middleware.new(*args, &block)
|
75
|
+
middleware = self.class::Middleware.new(*args, **kwargs, &block)
|
76
76
|
middlewares.insert(index, middleware)
|
77
77
|
end
|
78
78
|
|
@@ -83,8 +83,8 @@ module Grape
|
|
83
83
|
insert(index + 1, *args, &block)
|
84
84
|
end
|
85
85
|
|
86
|
-
def use(*args, &block)
|
87
|
-
middleware = self.class::Middleware.new(*args, &block)
|
86
|
+
def use(*args, **kwargs, &block)
|
87
|
+
middleware = self.class::Middleware.new(*args, **kwargs, &block)
|
88
88
|
middlewares.push(middleware)
|
89
89
|
end
|
90
90
|
|
@@ -4,7 +4,7 @@ module Grape
|
|
4
4
|
class Router
|
5
5
|
# this could be an OpenStruct, but doesn't work in Ruby 2.3.0, see https://bugs.ruby-lang.org/issues/12251
|
6
6
|
class AttributeTranslator
|
7
|
-
attr_reader :attributes
|
7
|
+
attr_reader :attributes
|
8
8
|
|
9
9
|
ROUTE_ATTRIBUTES = %i[
|
10
10
|
prefix
|
@@ -48,6 +48,14 @@ module Grape
|
|
48
48
|
def yield_attributes(_resource_params, _attrs)
|
49
49
|
raise NotImplementedError
|
50
50
|
end
|
51
|
+
|
52
|
+
# This is a special case so that we can ignore tree's where option
|
53
|
+
# values are missing lower down. Unfortunately we can remove this
|
54
|
+
# are the parameter parsing stage as they are required to ensure
|
55
|
+
# the correct indexing is maintained
|
56
|
+
def skip?(val)
|
57
|
+
val == Grape::DSL::Parameters::EmptyOptionalValue
|
58
|
+
end
|
51
59
|
end
|
52
60
|
end
|
53
61
|
end
|
@@ -61,8 +61,9 @@ module Grape
|
|
61
61
|
end
|
62
62
|
|
63
63
|
return params.any? { |param| meets_dependency?(param, request_params) } if params.is_a?(Array)
|
64
|
-
|
65
|
-
params
|
64
|
+
|
65
|
+
# params might be anything what looks like a hash, so it must implement a `key?` method
|
66
|
+
return false unless params.respond_to?(:key?)
|
66
67
|
|
67
68
|
@dependent_on.each do |dependency|
|
68
69
|
if dependency.is_a?(Hash)
|
@@ -43,7 +43,8 @@ module Grape
|
|
43
43
|
# there may be more than one error per field
|
44
44
|
array_errors = []
|
45
45
|
|
46
|
-
attributes.each do |val, attr_name, empty_val|
|
46
|
+
attributes.each do |val, attr_name, empty_val, skip_value|
|
47
|
+
next if skip_value
|
47
48
|
next if !@scope.required? && empty_val
|
48
49
|
next unless @scope.meets_dependency?(val, params)
|
49
50
|
begin
|
@@ -7,7 +7,8 @@ module Grape
|
|
7
7
|
attributes = MultipleAttributesIterator.new(self, @scope, params)
|
8
8
|
array_errors = []
|
9
9
|
|
10
|
-
attributes.each do |resource_params|
|
10
|
+
attributes.each do |resource_params, skip_value|
|
11
|
+
next if skip_value
|
11
12
|
begin
|
12
13
|
validate_params!(resource_params)
|
13
14
|
rescue Grape::Exceptions::Validation => e
|
data/lib/grape/version.rb
CHANGED
@@ -16,6 +16,7 @@ describe Grape::Endpoint do
|
|
16
16
|
requires :first
|
17
17
|
optional :second
|
18
18
|
optional :third, default: 'third-default'
|
19
|
+
optional :multiple_types, types: [Integer, String]
|
19
20
|
optional :nested, type: Hash do
|
20
21
|
optional :fourth
|
21
22
|
optional :fifth
|
@@ -96,6 +97,16 @@ describe Grape::Endpoint do
|
|
96
97
|
expect(JSON.parse(last_response.body)['nested']['fourth']).to be_nil
|
97
98
|
end
|
98
99
|
|
100
|
+
it 'should show nil for multiple allowed types if include_missing is true' do
|
101
|
+
subject.get '/declared' do
|
102
|
+
declared(params, include_missing: true)
|
103
|
+
end
|
104
|
+
|
105
|
+
get '/declared?first=present'
|
106
|
+
expect(last_response.status).to eq(200)
|
107
|
+
expect(JSON.parse(last_response.body)['multiple_types']).to be_nil
|
108
|
+
end
|
109
|
+
|
99
110
|
it 'does not work in a before filter' do
|
100
111
|
subject.before do
|
101
112
|
declared(params)
|
@@ -113,7 +124,7 @@ describe Grape::Endpoint do
|
|
113
124
|
end
|
114
125
|
get '/declared?first=present'
|
115
126
|
expect(last_response.status).to eq(200)
|
116
|
-
expect(JSON.parse(last_response.body).keys.size).to eq(
|
127
|
+
expect(JSON.parse(last_response.body).keys.size).to eq(11)
|
117
128
|
end
|
118
129
|
|
119
130
|
it 'has a optional param with default value all the time' do
|
@@ -13,8 +13,8 @@ describe Grape::Validations::MultipleAttributesIterator do
|
|
13
13
|
{ first: 'string', second: 'string' }
|
14
14
|
end
|
15
15
|
|
16
|
-
it 'yields the whole params hash without the list of attrs' do
|
17
|
-
expect { |b| iterator.each(&b) }.to yield_with_args(params)
|
16
|
+
it 'yields the whole params hash and the skipped flag without the list of attrs' do
|
17
|
+
expect { |b| iterator.each(&b) }.to yield_with_args(params, false)
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
@@ -24,7 +24,17 @@ describe Grape::Validations::MultipleAttributesIterator do
|
|
24
24
|
end
|
25
25
|
|
26
26
|
it 'yields each element of the array without the list of attrs' do
|
27
|
-
expect { |b| iterator.each(&b) }.to yield_successive_args(params[0], params[1])
|
27
|
+
expect { |b| iterator.each(&b) }.to yield_successive_args([params[0], false], [params[1], false])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'when params is empty optional placeholder' do
|
32
|
+
let(:params) do
|
33
|
+
[Grape::DSL::Parameters::EmptyOptionalValue, { first: 'string2', second: 'string2' }]
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'yields each element of the array without the list of attrs' do
|
37
|
+
expect { |b| iterator.each(&b) }.to yield_successive_args([Grape::DSL::Parameters::EmptyOptionalValue, true], [params[1], false])
|
28
38
|
end
|
29
39
|
end
|
30
40
|
end
|
@@ -15,7 +15,7 @@ describe Grape::Validations::SingleAttributeIterator do
|
|
15
15
|
|
16
16
|
it 'yields params and every single attribute from the list' do
|
17
17
|
expect { |b| iterator.each(&b) }
|
18
|
-
.to yield_successive_args([params, :first, false], [params, :second, false])
|
18
|
+
.to yield_successive_args([params, :first, false, false], [params, :second, false, false])
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
@@ -26,8 +26,8 @@ describe Grape::Validations::SingleAttributeIterator do
|
|
26
26
|
|
27
27
|
it 'yields every single attribute from the list for each of the array elements' do
|
28
28
|
expect { |b| iterator.each(&b) }.to yield_successive_args(
|
29
|
-
[params[0], :first, false], [params[0], :second, false],
|
30
|
-
[params[1], :first, false], [params[1], :second, false]
|
29
|
+
[params[0], :first, false, false], [params[0], :second, false, false],
|
30
|
+
[params[1], :first, false, false], [params[1], :second, false, false]
|
31
31
|
)
|
32
32
|
end
|
33
33
|
|
@@ -36,9 +36,20 @@ describe Grape::Validations::SingleAttributeIterator do
|
|
36
36
|
|
37
37
|
it 'marks params with empty values' do
|
38
38
|
expect { |b| iterator.each(&b) }.to yield_successive_args(
|
39
|
-
[params[0], :first, true], [params[0], :second, true],
|
40
|
-
[params[1], :first, true], [params[1], :second, true],
|
41
|
-
[params[2], :first, false], [params[2], :second, false]
|
39
|
+
[params[0], :first, true, false], [params[0], :second, true, false],
|
40
|
+
[params[1], :first, true, false], [params[1], :second, true, false],
|
41
|
+
[params[2], :first, false, false], [params[2], :second, false, false]
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'when missing optional value' do
|
47
|
+
let(:params) { [Grape::DSL::Parameters::EmptyOptionalValue, 10] }
|
48
|
+
|
49
|
+
it 'marks params with skipped values' do
|
50
|
+
expect { |b| iterator.each(&b) }.to yield_successive_args(
|
51
|
+
[params[0], :first, false, true], [params[0], :second, false, true],
|
52
|
+
[params[1], :first, false, false], [params[1], :second, false, false],
|
42
53
|
)
|
43
54
|
end
|
44
55
|
end
|
@@ -883,6 +883,274 @@ describe Grape::Validations do
|
|
883
883
|
end
|
884
884
|
expect(declared_params).to eq([items: [:key, { optional_subitems: [:value] }, { required_subitems: [:value] }]])
|
885
885
|
end
|
886
|
+
|
887
|
+
context <<~DESC do
|
888
|
+
Issue occurs whenever:
|
889
|
+
* 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
|
892
|
+
* 3rd level is a required item (can be any type)
|
893
|
+
* additional levels do not effect the issue from occuring
|
894
|
+
DESC
|
895
|
+
|
896
|
+
it "example based off actual real world use case" do
|
897
|
+
subject.params do
|
898
|
+
requires :orders, type: Array do
|
899
|
+
requires :id, type: Integer
|
900
|
+
optional :drugs, type: Array do
|
901
|
+
requires :batches, type: Array do
|
902
|
+
requires :batch_no, type: String
|
903
|
+
end
|
904
|
+
end
|
905
|
+
end
|
906
|
+
end
|
907
|
+
|
908
|
+
subject.get '/validate_required_arrays_under_optional_arrays' do
|
909
|
+
'validate_required_arrays_under_optional_arrays works!'
|
910
|
+
end
|
911
|
+
|
912
|
+
data = {
|
913
|
+
orders: [
|
914
|
+
{ id: 77, drugs: [{batches: [{batch_no: "A1234567"}]}]},
|
915
|
+
{ id: 70 }
|
916
|
+
]
|
917
|
+
}
|
918
|
+
|
919
|
+
get '/validate_required_arrays_under_optional_arrays', data
|
920
|
+
expect(last_response.body).to eq("validate_required_arrays_under_optional_arrays works!")
|
921
|
+
expect(last_response.status).to eq(200)
|
922
|
+
end
|
923
|
+
|
924
|
+
it "simplest example using Arry -> Array -> Hash -> String" do
|
925
|
+
subject.params do
|
926
|
+
requires :orders, type: Array do
|
927
|
+
requires :id, type: Integer
|
928
|
+
optional :drugs, type: Array do
|
929
|
+
requires :batch_no, type: String
|
930
|
+
end
|
931
|
+
end
|
932
|
+
end
|
933
|
+
|
934
|
+
subject.get '/validate_required_arrays_under_optional_arrays' do
|
935
|
+
'validate_required_arrays_under_optional_arrays works!'
|
936
|
+
end
|
937
|
+
|
938
|
+
data = {
|
939
|
+
orders: [
|
940
|
+
{ id: 77, drugs: [{batch_no: "A1234567"}]},
|
941
|
+
{ id: 70 }
|
942
|
+
]
|
943
|
+
}
|
944
|
+
|
945
|
+
get '/validate_required_arrays_under_optional_arrays', data
|
946
|
+
expect(last_response.body).to eq("validate_required_arrays_under_optional_arrays works!")
|
947
|
+
expect(last_response.status).to eq(200)
|
948
|
+
end
|
949
|
+
|
950
|
+
it "simplest example using Arry -> Hash -> String" do
|
951
|
+
subject.params do
|
952
|
+
requires :orders, type: Array do
|
953
|
+
requires :id, type: Integer
|
954
|
+
optional :drugs, type: Hash do
|
955
|
+
requires :batch_no, type: String
|
956
|
+
end
|
957
|
+
end
|
958
|
+
end
|
959
|
+
|
960
|
+
subject.get '/validate_required_arrays_under_optional_arrays' do
|
961
|
+
'validate_required_arrays_under_optional_arrays works!'
|
962
|
+
end
|
963
|
+
|
964
|
+
data = {
|
965
|
+
orders: [
|
966
|
+
{ id: 77, drugs: {batch_no: "A1234567"}},
|
967
|
+
{ id: 70 }
|
968
|
+
]
|
969
|
+
}
|
970
|
+
|
971
|
+
get '/validate_required_arrays_under_optional_arrays', data
|
972
|
+
expect(last_response.body).to eq("validate_required_arrays_under_optional_arrays works!")
|
973
|
+
expect(last_response.status).to eq(200)
|
974
|
+
end
|
975
|
+
|
976
|
+
it "correctly indexes invalida data" do
|
977
|
+
subject.params do
|
978
|
+
requires :orders, type: Array do
|
979
|
+
requires :id, type: Integer
|
980
|
+
optional :drugs, type: Array do
|
981
|
+
requires :batch_no, type: String
|
982
|
+
requires :quantity, type: Integer
|
983
|
+
end
|
984
|
+
end
|
985
|
+
end
|
986
|
+
|
987
|
+
subject.get '/correctly_indexes' do
|
988
|
+
'correctly_indexes works!'
|
989
|
+
end
|
990
|
+
|
991
|
+
data = {
|
992
|
+
orders: [
|
993
|
+
{ id: 70 },
|
994
|
+
{ id: 77, drugs: [{batch_no: "A1234567", quantity: 12}, {batch_no: "B222222"}]}
|
995
|
+
]
|
996
|
+
}
|
997
|
+
|
998
|
+
get '/correctly_indexes', data
|
999
|
+
expect(last_response.body).to eq("orders[1][drugs][1][quantity] is missing")
|
1000
|
+
expect(last_response.status).to eq(400)
|
1001
|
+
end
|
1002
|
+
|
1003
|
+
context "multiple levels of optional and requires settings" do
|
1004
|
+
before do
|
1005
|
+
subject.params do
|
1006
|
+
requires :top, type: Array do
|
1007
|
+
requires :top_id, type: Integer, allow_blank: false
|
1008
|
+
optional :middle_1, type: Array do
|
1009
|
+
requires :middle_1_id, type: Integer, allow_blank: false
|
1010
|
+
optional :middle_2, type: Array do
|
1011
|
+
requires :middle_2_id, type: String, allow_blank: false
|
1012
|
+
optional :bottom, type: Array do
|
1013
|
+
requires :bottom_id, type: Integer, allow_blank: false
|
1014
|
+
end
|
1015
|
+
end
|
1016
|
+
end
|
1017
|
+
end
|
1018
|
+
end
|
1019
|
+
|
1020
|
+
subject.get '/multi_level' do
|
1021
|
+
'multi_level works!'
|
1022
|
+
end
|
1023
|
+
end
|
1024
|
+
|
1025
|
+
it "with valid data" do
|
1026
|
+
data = {
|
1027
|
+
top: [
|
1028
|
+
{ 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}]}]}]},
|
1031
|
+
{ top_id: 2, middle_1: [
|
1032
|
+
{middle_1_id: 21}, {middle_1_id: 22, middle_2: [
|
1033
|
+
{middle_2_id: 221}]}]},
|
1034
|
+
{ top_id: 3, middle_1: [
|
1035
|
+
{middle_1_id: 31}, {middle_1_id: 32}]},
|
1036
|
+
{ top_id: 4 }
|
1037
|
+
]
|
1038
|
+
}
|
1039
|
+
|
1040
|
+
get '/multi_level', data
|
1041
|
+
expect(last_response.body).to eq("multi_level works!")
|
1042
|
+
expect(last_response.status).to eq(200)
|
1043
|
+
end
|
1044
|
+
|
1045
|
+
it "with invalid data" do
|
1046
|
+
data = {
|
1047
|
+
top: [
|
1048
|
+
{ top_id: 1, middle_1: [
|
1049
|
+
{middle_1_id: 11}, {middle_1_id: 12, middle_2: [
|
1050
|
+
{middle_2_id: 121}, {middle_2_id: 122, bottom: [{bottom_id: nil}]}]}]},
|
1051
|
+
{ top_id: 2, middle_1: [
|
1052
|
+
{middle_1_id: 21}, {middle_1_id: 22, middle_2: [{middle_2_id: nil}]}]},
|
1053
|
+
{ top_id: 3, middle_1: [
|
1054
|
+
{middle_1_id: nil}, {middle_1_id: 32}]},
|
1055
|
+
{ top_id: nil, missing_top_id: 4 }
|
1056
|
+
]
|
1057
|
+
}
|
1058
|
+
# debugger
|
1059
|
+
get '/multi_level', data
|
1060
|
+
expect(last_response.body.split(", ")).to match_array([
|
1061
|
+
"top[3][top_id] is empty",
|
1062
|
+
"top[2][middle_1][0][middle_1_id] is empty",
|
1063
|
+
"top[1][middle_1][1][middle_2][0][middle_2_id] is empty",
|
1064
|
+
"top[0][middle_1][1][middle_2][1][bottom][0][bottom_id] is empty"
|
1065
|
+
])
|
1066
|
+
expect(last_response.status).to eq(400)
|
1067
|
+
end
|
1068
|
+
end
|
1069
|
+
end
|
1070
|
+
|
1071
|
+
it "exactly_one_of" do
|
1072
|
+
subject.params do
|
1073
|
+
requires :orders, type: Array do
|
1074
|
+
requires :id, type: Integer
|
1075
|
+
optional :drugs, type: Hash do
|
1076
|
+
optional :batch_no, type: String
|
1077
|
+
optional :batch_id, type: String
|
1078
|
+
exactly_one_of :batch_no, :batch_id
|
1079
|
+
end
|
1080
|
+
end
|
1081
|
+
end
|
1082
|
+
|
1083
|
+
subject.get '/exactly_one_of' do
|
1084
|
+
'exactly_one_of works!'
|
1085
|
+
end
|
1086
|
+
|
1087
|
+
data = {
|
1088
|
+
orders: [
|
1089
|
+
{ id: 77, drugs: {batch_no: "A1234567"}},
|
1090
|
+
{ id: 70 }
|
1091
|
+
]
|
1092
|
+
}
|
1093
|
+
|
1094
|
+
get '/exactly_one_of', data
|
1095
|
+
expect(last_response.body).to eq("exactly_one_of works!")
|
1096
|
+
expect(last_response.status).to eq(200)
|
1097
|
+
end
|
1098
|
+
|
1099
|
+
it "at_least_one_of" do
|
1100
|
+
subject.params do
|
1101
|
+
requires :orders, type: Array do
|
1102
|
+
requires :id, type: Integer
|
1103
|
+
optional :drugs, type: Hash do
|
1104
|
+
optional :batch_no, type: String
|
1105
|
+
optional :batch_id, type: String
|
1106
|
+
at_least_one_of :batch_no, :batch_id
|
1107
|
+
end
|
1108
|
+
end
|
1109
|
+
end
|
1110
|
+
|
1111
|
+
subject.get '/at_least_one_of' do
|
1112
|
+
'at_least_one_of works!'
|
1113
|
+
end
|
1114
|
+
|
1115
|
+
data = {
|
1116
|
+
orders: [
|
1117
|
+
{ id: 77, drugs: {batch_no: "A1234567"}},
|
1118
|
+
{ id: 70 }
|
1119
|
+
]
|
1120
|
+
}
|
1121
|
+
|
1122
|
+
get '/at_least_one_of', data
|
1123
|
+
expect(last_response.body).to eq("at_least_one_of works!")
|
1124
|
+
expect(last_response.status).to eq(200)
|
1125
|
+
end
|
1126
|
+
|
1127
|
+
it "all_or_none_of" do
|
1128
|
+
subject.params do
|
1129
|
+
requires :orders, type: Array do
|
1130
|
+
requires :id, type: Integer
|
1131
|
+
optional :drugs, type: Hash do
|
1132
|
+
optional :batch_no, type: String
|
1133
|
+
optional :batch_id, type: String
|
1134
|
+
all_or_none_of :batch_no, :batch_id
|
1135
|
+
end
|
1136
|
+
end
|
1137
|
+
end
|
1138
|
+
|
1139
|
+
subject.get '/all_or_none_of' do
|
1140
|
+
'all_or_none_of works!'
|
1141
|
+
end
|
1142
|
+
|
1143
|
+
data = {
|
1144
|
+
orders: [
|
1145
|
+
{ id: 77, drugs: {batch_no: "A1234567", batch_id: "12"}},
|
1146
|
+
{ id: 70 }
|
1147
|
+
]
|
1148
|
+
}
|
1149
|
+
|
1150
|
+
get '/all_or_none_of', data
|
1151
|
+
expect(last_response.body).to eq("all_or_none_of works!")
|
1152
|
+
expect(last_response.status).to eq(200)
|
1153
|
+
end
|
886
1154
|
end
|
887
1155
|
|
888
1156
|
context 'multiple validation errors' do
|
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.5.
|
4
|
+
version: 1.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Bleigh
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-11-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -369,10 +369,10 @@ licenses:
|
|
369
369
|
- MIT
|
370
370
|
metadata:
|
371
371
|
bug_tracker_uri: https://github.com/ruby-grape/grape/issues
|
372
|
-
changelog_uri: https://github.com/ruby-grape/grape/blob/v1.5.
|
373
|
-
documentation_uri: https://www.rubydoc.info/gems/grape/1.5.
|
374
|
-
source_code_uri: https://github.com/ruby-grape/grape/tree/v1.5.
|
375
|
-
post_install_message:
|
372
|
+
changelog_uri: https://github.com/ruby-grape/grape/blob/v1.5.1/CHANGELOG.md
|
373
|
+
documentation_uri: https://www.rubydoc.info/gems/grape/1.5.1
|
374
|
+
source_code_uri: https://github.com/ruby-grape/grape/tree/v1.5.1
|
375
|
+
post_install_message:
|
376
376
|
rdoc_options: []
|
377
377
|
require_paths:
|
378
378
|
- lib
|
@@ -387,123 +387,123 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
387
387
|
- !ruby/object:Gem::Version
|
388
388
|
version: '0'
|
389
389
|
requirements: []
|
390
|
-
rubygems_version: 3.
|
391
|
-
signing_key:
|
390
|
+
rubygems_version: 3.0.3
|
391
|
+
signing_key:
|
392
392
|
specification_version: 4
|
393
393
|
summary: A simple Ruby framework for building REST-like APIs.
|
394
394
|
test_files:
|
395
|
-
- spec/spec_helper.rb
|
396
|
-
- spec/integration/eager_load/eager_load_spec.rb
|
397
|
-
- spec/integration/multi_xml/xml_spec.rb
|
398
|
-
- spec/integration/multi_json/json_spec.rb
|
399
395
|
- spec/shared/versioning_examples.rb
|
400
|
-
- spec/support/basic_auth_encode_helpers.rb
|
401
|
-
- spec/support/endpoint_faker.rb
|
402
|
-
- spec/support/chunks.rb
|
403
|
-
- spec/support/file_streamer.rb
|
404
396
|
- spec/support/versioned_helpers.rb
|
405
397
|
- spec/support/content_type_helpers.rb
|
406
398
|
- spec/support/eager_load.rb
|
399
|
+
- spec/support/basic_auth_encode_helpers.rb
|
400
|
+
- spec/support/file_streamer.rb
|
401
|
+
- spec/support/chunks.rb
|
402
|
+
- spec/support/endpoint_faker.rb
|
407
403
|
- spec/support/integer_helpers.rb
|
408
|
-
- spec/grape/
|
409
|
-
- spec/grape/
|
410
|
-
- spec/grape/
|
411
|
-
- spec/grape/
|
412
|
-
- spec/grape/
|
413
|
-
- spec/grape/
|
414
|
-
- spec/grape/
|
415
|
-
- spec/grape/
|
416
|
-
- spec/grape/
|
417
|
-
- spec/grape/
|
418
|
-
- spec/grape/
|
419
|
-
- spec/grape/
|
420
|
-
- spec/grape/
|
421
|
-
- spec/grape/
|
422
|
-
- spec/grape/
|
423
|
-
- spec/grape/
|
424
|
-
- spec/grape/
|
425
|
-
- spec/grape/
|
426
|
-
- spec/grape/
|
427
|
-
- spec/grape/util/stackable_values_spec.rb
|
428
|
-
- spec/grape/util/inheritable_setting_spec.rb
|
429
|
-
- spec/grape/util/strict_hash_configuration_spec.rb
|
430
|
-
- spec/grape/util/inheritable_values_spec.rb
|
431
|
-
- spec/grape/integration/rack_spec.rb
|
432
|
-
- spec/grape/integration/rack_sendfile_spec.rb
|
433
|
-
- spec/grape/integration/global_namespace_function_spec.rb
|
434
|
-
- spec/grape/validations_spec.rb
|
435
|
-
- spec/grape/entity_spec.rb
|
436
|
-
- spec/grape/exceptions/validation_spec.rb
|
437
|
-
- spec/grape/exceptions/invalid_accept_header_spec.rb
|
438
|
-
- spec/grape/exceptions/missing_option_spec.rb
|
439
|
-
- spec/grape/exceptions/invalid_response_spec.rb
|
440
|
-
- spec/grape/exceptions/body_parse_errors_spec.rb
|
441
|
-
- spec/grape/exceptions/invalid_formatter_spec.rb
|
442
|
-
- spec/grape/exceptions/missing_mime_type_spec.rb
|
443
|
-
- spec/grape/exceptions/unknown_options_spec.rb
|
444
|
-
- spec/grape/exceptions/validation_errors_spec.rb
|
445
|
-
- spec/grape/exceptions/unknown_validator_spec.rb
|
446
|
-
- spec/grape/exceptions/invalid_versioner_option_spec.rb
|
447
|
-
- spec/grape/exceptions/base_spec.rb
|
448
|
-
- spec/grape/presenters/presenter_spec.rb
|
449
|
-
- spec/grape/validations/single_attribute_iterator_spec.rb
|
404
|
+
- spec/grape/api/namespace_parameters_in_route_spec.rb
|
405
|
+
- spec/grape/api/routes_with_requirements_spec.rb
|
406
|
+
- spec/grape/api/nested_helpers_spec.rb
|
407
|
+
- spec/grape/api/required_parameters_in_route_spec.rb
|
408
|
+
- spec/grape/api/shared_helpers_exactly_one_of_spec.rb
|
409
|
+
- spec/grape/api/parameters_modification_spec.rb
|
410
|
+
- spec/grape/api/optional_parameters_in_route_spec.rb
|
411
|
+
- spec/grape/api/inherited_helpers_spec.rb
|
412
|
+
- spec/grape/api/required_parameters_with_invalid_method_spec.rb
|
413
|
+
- spec/grape/api/custom_validations_spec.rb
|
414
|
+
- spec/grape/api/defines_boolean_in_params_spec.rb
|
415
|
+
- spec/grape/api/shared_helpers_spec.rb
|
416
|
+
- spec/grape/api/invalid_format_spec.rb
|
417
|
+
- spec/grape/api/deeply_included_options_spec.rb
|
418
|
+
- spec/grape/api/instance_spec.rb
|
419
|
+
- spec/grape/api/patch_method_helpers_spec.rb
|
420
|
+
- spec/grape/api/recognize_path_spec.rb
|
421
|
+
- spec/grape/api_remount_spec.rb
|
422
|
+
- spec/grape/validations/types_spec.rb
|
450
423
|
- spec/grape/validations/attributes_iterator_spec.rb
|
451
|
-
- spec/grape/validations/types/primitive_coercer_spec.rb
|
452
|
-
- spec/grape/validations/types/set_coercer_spec.rb
|
453
424
|
- spec/grape/validations/types/array_coercer_spec.rb
|
454
|
-
- spec/grape/validations/
|
455
|
-
- spec/grape/validations/
|
456
|
-
- spec/grape/validations/multiple_attributes_iterator_spec.rb
|
457
|
-
- spec/grape/validations/types_spec.rb
|
425
|
+
- spec/grape/validations/types/set_coercer_spec.rb
|
426
|
+
- spec/grape/validations/types/primitive_coercer_spec.rb
|
458
427
|
- spec/grape/validations/validators/regexp_spec.rb
|
428
|
+
- spec/grape/validations/validators/default_spec.rb
|
429
|
+
- spec/grape/validations/validators/values_spec.rb
|
430
|
+
- spec/grape/validations/validators/same_as_spec.rb
|
459
431
|
- spec/grape/validations/validators/mutual_exclusion_spec.rb
|
460
|
-
- spec/grape/validations/validators/exactly_one_of_spec.rb
|
461
432
|
- spec/grape/validations/validators/except_values_spec.rb
|
462
|
-
- spec/grape/validations/validators/
|
463
|
-
- spec/grape/validations/validators/all_or_none_spec.rb
|
433
|
+
- spec/grape/validations/validators/exactly_one_of_spec.rb
|
464
434
|
- spec/grape/validations/validators/allow_blank_spec.rb
|
465
|
-
- spec/grape/validations/validators/same_as_spec.rb
|
466
|
-
- spec/grape/validations/validators/default_spec.rb
|
467
|
-
- spec/grape/validations/validators/values_spec.rb
|
468
|
-
- spec/grape/validations/validators/at_least_one_of_spec.rb
|
469
435
|
- spec/grape/validations/validators/coerce_spec.rb
|
436
|
+
- spec/grape/validations/validators/presence_spec.rb
|
437
|
+
- spec/grape/validations/validators/at_least_one_of_spec.rb
|
470
438
|
- spec/grape/validations/validators/zh-CN.yml
|
471
|
-
- spec/grape/
|
472
|
-
- spec/grape/
|
473
|
-
- spec/grape/
|
439
|
+
- spec/grape/validations/validators/all_or_none_spec.rb
|
440
|
+
- spec/grape/validations/params_scope_spec.rb
|
441
|
+
- spec/grape/validations/multiple_attributes_iterator_spec.rb
|
442
|
+
- spec/grape/validations/instance_behaivour_spec.rb
|
443
|
+
- spec/grape/validations/single_attribute_iterator_spec.rb
|
444
|
+
- spec/grape/config_spec.rb
|
474
445
|
- spec/grape/parser_spec.rb
|
475
|
-
- spec/grape/
|
446
|
+
- spec/grape/exceptions/body_parse_errors_spec.rb
|
447
|
+
- spec/grape/exceptions/missing_option_spec.rb
|
448
|
+
- spec/grape/exceptions/invalid_accept_header_spec.rb
|
449
|
+
- spec/grape/exceptions/validation_spec.rb
|
450
|
+
- spec/grape/exceptions/unknown_validator_spec.rb
|
451
|
+
- spec/grape/exceptions/validation_errors_spec.rb
|
452
|
+
- spec/grape/exceptions/invalid_response_spec.rb
|
453
|
+
- spec/grape/exceptions/unknown_options_spec.rb
|
454
|
+
- spec/grape/exceptions/invalid_formatter_spec.rb
|
455
|
+
- spec/grape/exceptions/invalid_versioner_option_spec.rb
|
456
|
+
- spec/grape/exceptions/missing_mime_type_spec.rb
|
457
|
+
- spec/grape/exceptions/base_spec.rb
|
458
|
+
- spec/grape/path_spec.rb
|
459
|
+
- spec/grape/util/stackable_values_spec.rb
|
460
|
+
- spec/grape/util/strict_hash_configuration_spec.rb
|
461
|
+
- spec/grape/util/inheritable_setting_spec.rb
|
462
|
+
- spec/grape/util/reverse_stackable_values_spec.rb
|
463
|
+
- spec/grape/util/inheritable_values_spec.rb
|
464
|
+
- spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb
|
465
|
+
- spec/grape/extensions/param_builders/hash_spec.rb
|
466
|
+
- spec/grape/extensions/param_builders/hashie/mash_spec.rb
|
467
|
+
- spec/grape/integration/rack_spec.rb
|
468
|
+
- spec/grape/integration/rack_sendfile_spec.rb
|
469
|
+
- spec/grape/integration/global_namespace_function_spec.rb
|
476
470
|
- spec/grape/endpoint/declared_spec.rb
|
477
|
-
- spec/grape/
|
478
|
-
- spec/grape/
|
479
|
-
- spec/grape/
|
480
|
-
- spec/grape/
|
481
|
-
- spec/grape/
|
482
|
-
- spec/grape/
|
483
|
-
- spec/grape/
|
484
|
-
- spec/grape/
|
485
|
-
- spec/grape/
|
486
|
-
- spec/grape/
|
487
|
-
- spec/grape/
|
488
|
-
- spec/grape/
|
489
|
-
- spec/grape/
|
490
|
-
- spec/grape/
|
491
|
-
- spec/grape/
|
492
|
-
- spec/grape/
|
493
|
-
- spec/grape/
|
494
|
-
- spec/grape/
|
495
|
-
- spec/grape/
|
496
|
-
- spec/grape/dsl/
|
497
|
-
- spec/grape/dsl/
|
498
|
-
- spec/grape/dsl/
|
471
|
+
- spec/grape/presenters/presenter_spec.rb
|
472
|
+
- spec/grape/endpoint_spec.rb
|
473
|
+
- spec/grape/api_spec.rb
|
474
|
+
- spec/grape/middleware/exception_spec.rb
|
475
|
+
- spec/grape/middleware/versioner/param_spec.rb
|
476
|
+
- spec/grape/middleware/versioner/header_spec.rb
|
477
|
+
- spec/grape/middleware/versioner/path_spec.rb
|
478
|
+
- spec/grape/middleware/versioner/accept_version_header_spec.rb
|
479
|
+
- spec/grape/middleware/globals_spec.rb
|
480
|
+
- spec/grape/middleware/stack_spec.rb
|
481
|
+
- spec/grape/middleware/formatter_spec.rb
|
482
|
+
- spec/grape/middleware/error_spec.rb
|
483
|
+
- spec/grape/middleware/auth/dsl_spec.rb
|
484
|
+
- spec/grape/middleware/auth/strategies_spec.rb
|
485
|
+
- spec/grape/middleware/auth/base_spec.rb
|
486
|
+
- spec/grape/middleware/versioner_spec.rb
|
487
|
+
- spec/grape/middleware/base_spec.rb
|
488
|
+
- spec/grape/entity_spec.rb
|
489
|
+
- spec/grape/dsl/settings_spec.rb
|
490
|
+
- spec/grape/dsl/callbacks_spec.rb
|
491
|
+
- spec/grape/dsl/middleware_spec.rb
|
492
|
+
- spec/grape/dsl/inside_route_spec.rb
|
499
493
|
- spec/grape/dsl/configuration_spec.rb
|
500
|
-
- spec/grape/dsl/validations_spec.rb
|
501
494
|
- spec/grape/dsl/parameters_spec.rb
|
495
|
+
- spec/grape/dsl/logger_spec.rb
|
502
496
|
- spec/grape/dsl/helpers_spec.rb
|
503
|
-
- spec/grape/dsl/
|
504
|
-
- spec/grape/dsl/headers_spec.rb
|
505
|
-
- spec/grape/dsl/callbacks_spec.rb
|
506
|
-
- spec/grape/dsl/settings_spec.rb
|
497
|
+
- spec/grape/dsl/request_response_spec.rb
|
507
498
|
- spec/grape/dsl/routing_spec.rb
|
508
|
-
- spec/grape/dsl/
|
509
|
-
- spec/grape/
|
499
|
+
- spec/grape/dsl/headers_spec.rb
|
500
|
+
- spec/grape/dsl/validations_spec.rb
|
501
|
+
- spec/grape/dsl/desc_spec.rb
|
502
|
+
- spec/grape/validations_spec.rb
|
503
|
+
- spec/grape/named_api_spec.rb
|
504
|
+
- spec/grape/loading_spec.rb
|
505
|
+
- spec/grape/request_spec.rb
|
506
|
+
- spec/integration/eager_load/eager_load_spec.rb
|
507
|
+
- spec/integration/multi_xml/xml_spec.rb
|
508
|
+
- spec/integration/multi_json/json_spec.rb
|
509
|
+
- spec/spec_helper.rb
|