grape 1.5.0 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +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
|