grape 0.11.0 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of grape might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +23 -80
- data/.travis.yml +1 -1
- data/CHANGELOG.md +27 -0
- data/Gemfile +1 -1
- data/Guardfile +1 -1
- data/LICENSE +1 -1
- data/README.md +131 -30
- data/Rakefile +1 -1
- data/UPGRADING.md +110 -1
- data/gemfiles/rails_3.gemfile +1 -1
- data/gemfiles/rails_4.gemfile +1 -1
- data/grape.gemspec +4 -4
- data/lib/grape.rb +92 -62
- data/lib/grape/api.rb +10 -10
- data/lib/grape/cookies.rb +1 -1
- data/lib/grape/dsl/configuration.rb +7 -7
- data/lib/grape/dsl/helpers.rb +3 -3
- data/lib/grape/dsl/inside_route.rb +50 -21
- data/lib/grape/dsl/parameters.rb +25 -6
- data/lib/grape/dsl/request_response.rb +1 -1
- data/lib/grape/dsl/routing.rb +11 -10
- data/lib/grape/dsl/settings.rb +1 -1
- data/lib/grape/endpoint.rb +21 -19
- data/lib/grape/error_formatter/json.rb +1 -1
- data/lib/grape/exceptions/base.rb +1 -1
- data/lib/grape/exceptions/validation.rb +1 -1
- data/lib/grape/exceptions/validation_errors.rb +2 -2
- data/lib/grape/formatter/base.rb +1 -1
- data/lib/grape/formatter/json.rb +1 -1
- data/lib/grape/formatter/serializable_hash.rb +4 -4
- data/lib/grape/formatter/txt.rb +1 -1
- data/lib/grape/formatter/xml.rb +1 -1
- data/lib/grape/http/headers.rb +27 -0
- data/lib/grape/http/request.rb +1 -1
- data/lib/grape/middleware/error.rb +10 -4
- data/lib/grape/middleware/formatter.rb +13 -9
- data/lib/grape/middleware/globals.rb +2 -1
- data/lib/grape/middleware/versioner/accept_version_header.rb +2 -2
- data/lib/grape/middleware/versioner/header.rb +4 -4
- data/lib/grape/middleware/versioner/param.rb +2 -2
- data/lib/grape/middleware/versioner/path.rb +1 -1
- data/lib/grape/namespace.rb +2 -1
- data/lib/grape/parser/json.rb +1 -1
- data/lib/grape/parser/xml.rb +1 -1
- data/lib/grape/path.rb +3 -3
- data/lib/grape/presenters/presenter.rb +9 -0
- data/lib/grape/validations/params_scope.rb +3 -3
- data/lib/grape/validations/validators/allow_blank.rb +1 -1
- data/lib/grape/validations/validators/coerce.rb +6 -5
- data/lib/grape/validations/validators/default.rb +2 -2
- data/lib/grape/validations/validators/multiple_params_base.rb +1 -0
- data/lib/grape/validations/validators/regexp.rb +1 -1
- data/lib/grape/version.rb +1 -1
- data/spec/grape/api/custom_validations_spec.rb +47 -0
- data/spec/grape/api/deeply_included_options_spec.rb +56 -0
- data/spec/grape/api_spec.rb +64 -42
- data/spec/grape/dsl/configuration_spec.rb +2 -2
- data/spec/grape/dsl/helpers_spec.rb +1 -1
- data/spec/grape/dsl/inside_route_spec.rb +75 -19
- data/spec/grape/dsl/parameters_spec.rb +59 -10
- data/spec/grape/dsl/request_response_spec.rb +62 -2
- data/spec/grape/dsl/routing_spec.rb +116 -18
- data/spec/grape/endpoint_spec.rb +57 -5
- data/spec/grape/entity_spec.rb +1 -1
- data/spec/grape/exceptions/body_parse_errors_spec.rb +5 -5
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +32 -32
- data/spec/grape/exceptions/validation_errors_spec.rb +1 -1
- data/spec/grape/integration/rack_spec.rb +4 -3
- data/spec/grape/middleware/auth/strategies_spec.rb +2 -2
- data/spec/grape/middleware/base_spec.rb +2 -2
- data/spec/grape/middleware/error_spec.rb +1 -1
- data/spec/grape/middleware/exception_spec.rb +5 -5
- data/spec/grape/middleware/formatter_spec.rb +10 -10
- data/spec/grape/middleware/globals_spec.rb +27 -0
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +1 -1
- data/spec/grape/middleware/versioner/header_spec.rb +1 -1
- data/spec/grape/middleware/versioner/param_spec.rb +1 -1
- data/spec/grape/middleware/versioner/path_spec.rb +1 -1
- data/spec/grape/path_spec.rb +6 -4
- data/spec/grape/presenters/presenter_spec.rb +70 -0
- data/spec/grape/util/inheritable_values_spec.rb +1 -1
- data/spec/grape/util/stackable_values_spec.rb +1 -1
- data/spec/grape/util/strict_hash_configuration_spec.rb +1 -1
- data/spec/grape/validations/params_scope_spec.rb +64 -0
- data/spec/grape/validations/validators/allow_blank_spec.rb +10 -0
- data/spec/grape/validations/validators/coerce_spec.rb +48 -18
- data/spec/grape/validations/validators/default_spec.rb +110 -20
- data/spec/grape/validations/validators/presence_spec.rb +41 -3
- data/spec/grape/validations/validators/regexp_spec.rb +7 -2
- data/spec/grape/validations_spec.rb +20 -1
- data/spec/support/file_streamer.rb +11 -0
- data/spec/support/versioned_helpers.rb +1 -1
- metadata +14 -2
@@ -40,20 +40,6 @@ describe Grape::Validations::DefaultValidator do
|
|
40
40
|
{ random_number: params[:random], non_random_number: params[:non_random_number] }
|
41
41
|
end
|
42
42
|
|
43
|
-
params do
|
44
|
-
# NOTE: The :foo parameter could be made required with json body
|
45
|
-
# params, and then an empty hash would be valid. With query parameters
|
46
|
-
# it must be optional if it isn't provided at all, as otherwise
|
47
|
-
# the validaton for the Hash itself fails because there is no such
|
48
|
-
# thing as an empty hash.
|
49
|
-
optional :foo, type: Hash do
|
50
|
-
optional :bar, default: 'foo-bar'
|
51
|
-
end
|
52
|
-
end
|
53
|
-
get '/group' do
|
54
|
-
{ foo_bar: params[:foo][:bar] }
|
55
|
-
end
|
56
|
-
|
57
43
|
params do
|
58
44
|
optional :array, type: Array do
|
59
45
|
requires :name
|
@@ -107,15 +93,119 @@ describe Grape::Validations::DefaultValidator do
|
|
107
93
|
expect(before['random_number']).not_to eq(after['random_number'])
|
108
94
|
end
|
109
95
|
|
110
|
-
it 'set default values for optional grouped params' do
|
111
|
-
get('/group')
|
112
|
-
expect(last_response.status).to eq(200)
|
113
|
-
expect(last_response.body).to eq({ foo_bar: 'foo-bar' }.to_json)
|
114
|
-
end
|
115
|
-
|
116
96
|
it 'sets default values for grouped arrays' do
|
117
97
|
get('/array?array[][name]=name&array[][name]=name2&array[][with_default]=bar2')
|
118
98
|
expect(last_response.status).to eq(200)
|
119
99
|
expect(last_response.body).to eq({ array: [{ name: 'name', with_default: 'default' }, { name: 'name2', with_default: 'bar2' }] }.to_json)
|
120
100
|
end
|
101
|
+
|
102
|
+
context 'optional group with defaults' do
|
103
|
+
subject do
|
104
|
+
Class.new(Grape::API) do
|
105
|
+
default_format :json
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def app
|
110
|
+
subject
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'optional array without default value includes optional param with default value' do
|
114
|
+
before do
|
115
|
+
subject.params do
|
116
|
+
optional :optional_array, type: Array do
|
117
|
+
optional :foo_in_optional_array, default: 'bar'
|
118
|
+
end
|
119
|
+
end
|
120
|
+
subject.post '/optional_array' do
|
121
|
+
{ optional_array: params[:optional_array] }
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'returns nil for optional array if param is not provided' do
|
126
|
+
post '/optional_array'
|
127
|
+
expect(last_response.status).to eq(201)
|
128
|
+
expect(last_response.body).to eq({ optional_array: nil }.to_json)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
context 'optional array with default value includes optional param with default value' do
|
133
|
+
before do
|
134
|
+
subject.params do
|
135
|
+
optional :optional_array_with_default, type: Array, default: [] do
|
136
|
+
optional :foo_in_optional_array, default: 'bar'
|
137
|
+
end
|
138
|
+
end
|
139
|
+
subject.post '/optional_array_with_default' do
|
140
|
+
{ optional_array_with_default: params[:optional_array_with_default] }
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'sets default value for optional array if param is not provided' do
|
145
|
+
post '/optional_array_with_default'
|
146
|
+
expect(last_response.status).to eq(201)
|
147
|
+
expect(last_response.body).to eq({ optional_array_with_default: [] }.to_json)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
context 'optional hash without default value includes optional param with default value' do
|
152
|
+
before do
|
153
|
+
subject.params do
|
154
|
+
optional :optional_hash_without_default, type: Hash do
|
155
|
+
optional :foo_in_optional_hash, default: 'bar'
|
156
|
+
end
|
157
|
+
end
|
158
|
+
subject.post '/optional_hash_without_default' do
|
159
|
+
{ optional_hash_without_default: params[:optional_hash_without_default] }
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'returns nil for optional hash if param is not provided' do
|
164
|
+
post '/optional_hash_without_default'
|
165
|
+
expect(last_response.status).to eq(201)
|
166
|
+
expect(last_response.body).to eq({ optional_hash_without_default: nil }.to_json)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
context 'optional hash with default value includes optional param with default value' do
|
171
|
+
before do
|
172
|
+
subject.params do
|
173
|
+
optional :optional_hash_with_default, type: Hash, default: {} do
|
174
|
+
optional :foo_in_optional_hash, default: 'bar'
|
175
|
+
end
|
176
|
+
end
|
177
|
+
subject.post '/optional_hash_with_default_empty_hash' do
|
178
|
+
{ optional_hash_with_default: params[:optional_hash_with_default] }
|
179
|
+
end
|
180
|
+
|
181
|
+
subject.params do
|
182
|
+
optional :optional_hash_with_default, type: Hash, default: { foo_in_optional_hash: 'parent_default' } do
|
183
|
+
optional :some_param
|
184
|
+
optional :foo_in_optional_hash, default: 'own_default'
|
185
|
+
end
|
186
|
+
end
|
187
|
+
subject.post '/optional_hash_with_default_inner_params' do
|
188
|
+
{ foo_in_optional_hash: params[:optional_hash_with_default][:foo_in_optional_hash] }
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'sets default value for optional hash if param is not provided' do
|
193
|
+
post '/optional_hash_with_default_empty_hash'
|
194
|
+
expect(last_response.status).to eq(201)
|
195
|
+
expect(last_response.body).to eq({ optional_hash_with_default: {} }.to_json)
|
196
|
+
end
|
197
|
+
|
198
|
+
it 'sets default value from parent defaults for inner param if parent param is not provided' do
|
199
|
+
post '/optional_hash_with_default_inner_params'
|
200
|
+
expect(last_response.status).to eq(201)
|
201
|
+
expect(last_response.body).to eq({ foo_in_optional_hash: 'parent_default' }.to_json)
|
202
|
+
end
|
203
|
+
|
204
|
+
it 'sets own default value for inner param if parent param is provided' do
|
205
|
+
post '/optional_hash_with_default_inner_params', optional_hash_with_default: { some_param: 'param' }
|
206
|
+
expect(last_response.status).to eq(201)
|
207
|
+
expect(last_response.body).to eq({ foo_in_optional_hash: 'own_default' }.to_json)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
121
211
|
end
|
@@ -55,7 +55,7 @@ describe Grape::Validations::PresenceValidator do
|
|
55
55
|
context 'with a required non-empty string' do
|
56
56
|
before do
|
57
57
|
subject.params do
|
58
|
-
requires :email, type: String, regexp: /^\S+$/
|
58
|
+
requires :email, type: String, allow_blank: false, regexp: /^\S+$/
|
59
59
|
end
|
60
60
|
subject.get do
|
61
61
|
'Hello'
|
@@ -64,12 +64,12 @@ describe Grape::Validations::PresenceValidator do
|
|
64
64
|
it 'requires when missing' do
|
65
65
|
get '/'
|
66
66
|
expect(last_response.status).to eq(400)
|
67
|
-
expect(last_response.body).to eq('{"error":"email is missing, email is
|
67
|
+
expect(last_response.body).to eq('{"error":"email is missing, email is empty"}')
|
68
68
|
end
|
69
69
|
it 'requires when empty' do
|
70
70
|
get '/', email: ''
|
71
71
|
expect(last_response.status).to eq(400)
|
72
|
-
expect(last_response.body).to eq('{"error":"email is invalid"}')
|
72
|
+
expect(last_response.body).to eq('{"error":"email is empty, email is invalid"}')
|
73
73
|
end
|
74
74
|
it 'valid when set' do
|
75
75
|
get '/', email: 'bob@example.com'
|
@@ -176,4 +176,42 @@ describe Grape::Validations::PresenceValidator do
|
|
176
176
|
expect(last_response.body).to eq('Nested triple'.to_json)
|
177
177
|
end
|
178
178
|
end
|
179
|
+
|
180
|
+
context 'with reused parameter documentation once required and once optional' do
|
181
|
+
before do
|
182
|
+
docs = { name: { type: String, desc: 'some name' } }
|
183
|
+
|
184
|
+
subject.params do
|
185
|
+
requires :all, using: docs
|
186
|
+
end
|
187
|
+
subject.get '/required' do
|
188
|
+
'Hello required'
|
189
|
+
end
|
190
|
+
|
191
|
+
subject.params do
|
192
|
+
optional :all, using: docs
|
193
|
+
end
|
194
|
+
subject.get '/optional' do
|
195
|
+
'Hello optional'
|
196
|
+
end
|
197
|
+
end
|
198
|
+
it 'works with required' do
|
199
|
+
get '/required'
|
200
|
+
expect(last_response.status).to eq(400)
|
201
|
+
expect(last_response.body).to eq('{"error":"name is missing"}')
|
202
|
+
|
203
|
+
get '/required', name: 'Bob'
|
204
|
+
expect(last_response.status).to eq(200)
|
205
|
+
expect(last_response.body).to eq('Hello required'.to_json)
|
206
|
+
end
|
207
|
+
it 'works with optional' do
|
208
|
+
get '/optional'
|
209
|
+
expect(last_response.status).to eq(200)
|
210
|
+
expect(last_response.body).to eq('Hello optional'.to_json)
|
211
|
+
|
212
|
+
get '/optional', name: 'Bob'
|
213
|
+
expect(last_response.status).to eq(200)
|
214
|
+
expect(last_response.body).to eq('Hello optional'.to_json)
|
215
|
+
end
|
216
|
+
end
|
179
217
|
end
|
@@ -25,12 +25,17 @@ describe Grape::Validations::RegexpValidator do
|
|
25
25
|
expect(last_response.status).to eq(400)
|
26
26
|
end
|
27
27
|
|
28
|
-
it 'refuses
|
29
|
-
get '/', name:
|
28
|
+
it 'refuses empty' do
|
29
|
+
get '/', name: ''
|
30
30
|
expect(last_response.status).to eq(400)
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
+
it 'accepts nil' do
|
35
|
+
get '/', name: nil
|
36
|
+
expect(last_response.status).to eq(200)
|
37
|
+
end
|
38
|
+
|
34
39
|
it 'accepts valid input' do
|
35
40
|
get '/', name: 'bob'
|
36
41
|
expect(last_response.status).to eq(200)
|
@@ -353,7 +353,7 @@ describe Grape::Validations do
|
|
353
353
|
end
|
354
354
|
|
355
355
|
context 'group params with nested params which has a type' do
|
356
|
-
let(:invalid_items){ { items: '' } }
|
356
|
+
let(:invalid_items) { { items: '' } }
|
357
357
|
|
358
358
|
before do
|
359
359
|
subject.params do
|
@@ -1132,6 +1132,25 @@ describe Grape::Validations do
|
|
1132
1132
|
expect(last_response.status).to eq(400)
|
1133
1133
|
end
|
1134
1134
|
end
|
1135
|
+
|
1136
|
+
context 'mutually exclusive params inside Hash group' do
|
1137
|
+
it 'invalidates if request param is invalid type' do
|
1138
|
+
subject.params do
|
1139
|
+
optional :wine, type: Hash do
|
1140
|
+
optional :grape
|
1141
|
+
optional :country
|
1142
|
+
mutually_exclusive :grape, :country
|
1143
|
+
end
|
1144
|
+
end
|
1145
|
+
subject.post '/mutually_exclusive' do
|
1146
|
+
'mutually_exclusive works!'
|
1147
|
+
end
|
1148
|
+
|
1149
|
+
post '/mutually_exclusive', wine: '2015 sauvignon'
|
1150
|
+
expect(last_response.status).to eq(400)
|
1151
|
+
expect(last_response.body).to eq 'wine is invalid'
|
1152
|
+
end
|
1153
|
+
end
|
1135
1154
|
end
|
1136
1155
|
|
1137
1156
|
context 'exactly one of' 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: 0.
|
4
|
+
version: 0.12.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: 2015-
|
11
|
+
date: 2015-06-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -360,6 +360,7 @@ files:
|
|
360
360
|
- lib/grape/formatter/serializable_hash.rb
|
361
361
|
- lib/grape/formatter/txt.rb
|
362
362
|
- lib/grape/formatter/xml.rb
|
363
|
+
- lib/grape/http/headers.rb
|
363
364
|
- lib/grape/http/request.rb
|
364
365
|
- lib/grape/locale/en.yml
|
365
366
|
- lib/grape/middleware/auth/base.rb
|
@@ -381,6 +382,7 @@ files:
|
|
381
382
|
- lib/grape/parser/json.rb
|
382
383
|
- lib/grape/parser/xml.rb
|
383
384
|
- lib/grape/path.rb
|
385
|
+
- lib/grape/presenters/presenter.rb
|
384
386
|
- lib/grape/route.rb
|
385
387
|
- lib/grape/util/content_types.rb
|
386
388
|
- lib/grape/util/inheritable_setting.rb
|
@@ -403,6 +405,8 @@ files:
|
|
403
405
|
- lib/grape/validations/validators/regexp.rb
|
404
406
|
- lib/grape/validations/validators/values.rb
|
405
407
|
- lib/grape/version.rb
|
408
|
+
- spec/grape/api/custom_validations_spec.rb
|
409
|
+
- spec/grape/api/deeply_included_options_spec.rb
|
406
410
|
- spec/grape/api/nested_helpers_spec.rb
|
407
411
|
- spec/grape/api/shared_helpers_spec.rb
|
408
412
|
- spec/grape/api_spec.rb
|
@@ -436,12 +440,14 @@ files:
|
|
436
440
|
- spec/grape/middleware/error_spec.rb
|
437
441
|
- spec/grape/middleware/exception_spec.rb
|
438
442
|
- spec/grape/middleware/formatter_spec.rb
|
443
|
+
- spec/grape/middleware/globals_spec.rb
|
439
444
|
- spec/grape/middleware/versioner/accept_version_header_spec.rb
|
440
445
|
- spec/grape/middleware/versioner/header_spec.rb
|
441
446
|
- spec/grape/middleware/versioner/param_spec.rb
|
442
447
|
- spec/grape/middleware/versioner/path_spec.rb
|
443
448
|
- spec/grape/middleware/versioner_spec.rb
|
444
449
|
- spec/grape/path_spec.rb
|
450
|
+
- spec/grape/presenters/presenter_spec.rb
|
445
451
|
- spec/grape/util/inheritable_setting_spec.rb
|
446
452
|
- spec/grape/util/inheritable_values_spec.rb
|
447
453
|
- spec/grape/util/stackable_values_spec.rb
|
@@ -465,6 +471,7 @@ files:
|
|
465
471
|
- spec/support/basic_auth_encode_helpers.rb
|
466
472
|
- spec/support/content_type_helpers.rb
|
467
473
|
- spec/support/endpoint_faker.rb
|
474
|
+
- spec/support/file_streamer.rb
|
468
475
|
- spec/support/versioned_helpers.rb
|
469
476
|
homepage: https://github.com/intridea/grape
|
470
477
|
licenses:
|
@@ -491,6 +498,8 @@ signing_key:
|
|
491
498
|
specification_version: 4
|
492
499
|
summary: A simple Ruby framework for building REST-like APIs.
|
493
500
|
test_files:
|
501
|
+
- spec/grape/api/custom_validations_spec.rb
|
502
|
+
- spec/grape/api/deeply_included_options_spec.rb
|
494
503
|
- spec/grape/api/nested_helpers_spec.rb
|
495
504
|
- spec/grape/api/shared_helpers_spec.rb
|
496
505
|
- spec/grape/api_spec.rb
|
@@ -524,12 +533,14 @@ test_files:
|
|
524
533
|
- spec/grape/middleware/error_spec.rb
|
525
534
|
- spec/grape/middleware/exception_spec.rb
|
526
535
|
- spec/grape/middleware/formatter_spec.rb
|
536
|
+
- spec/grape/middleware/globals_spec.rb
|
527
537
|
- spec/grape/middleware/versioner/accept_version_header_spec.rb
|
528
538
|
- spec/grape/middleware/versioner/header_spec.rb
|
529
539
|
- spec/grape/middleware/versioner/param_spec.rb
|
530
540
|
- spec/grape/middleware/versioner/path_spec.rb
|
531
541
|
- spec/grape/middleware/versioner_spec.rb
|
532
542
|
- spec/grape/path_spec.rb
|
543
|
+
- spec/grape/presenters/presenter_spec.rb
|
533
544
|
- spec/grape/util/inheritable_setting_spec.rb
|
534
545
|
- spec/grape/util/inheritable_values_spec.rb
|
535
546
|
- spec/grape/util/stackable_values_spec.rb
|
@@ -553,5 +564,6 @@ test_files:
|
|
553
564
|
- spec/support/basic_auth_encode_helpers.rb
|
554
565
|
- spec/support/content_type_helpers.rb
|
555
566
|
- spec/support/endpoint_faker.rb
|
567
|
+
- spec/support/file_streamer.rb
|
556
568
|
- spec/support/versioned_helpers.rb
|
557
569
|
has_rdoc:
|