grape 1.3.0 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +22 -0
  3. data/README.md +3 -4
  4. data/lib/grape.rb +2 -3
  5. data/lib/grape/api.rb +2 -2
  6. data/lib/grape/api/instance.rb +4 -4
  7. data/lib/grape/content_types.rb +34 -0
  8. data/lib/grape/dsl/helpers.rb +1 -1
  9. data/lib/grape/dsl/inside_route.rb +10 -9
  10. data/lib/grape/dsl/parameters.rb +4 -4
  11. data/lib/grape/dsl/routing.rb +6 -4
  12. data/lib/grape/exceptions/base.rb +0 -4
  13. data/lib/grape/exceptions/validation_errors.rb +11 -12
  14. data/lib/grape/http/headers.rb +25 -0
  15. data/lib/grape/middleware/base.rb +1 -3
  16. data/lib/grape/middleware/stack.rb +2 -1
  17. data/lib/grape/middleware/versioner/header.rb +3 -3
  18. data/lib/grape/middleware/versioner/path.rb +1 -1
  19. data/lib/grape/namespace.rb +12 -2
  20. data/lib/grape/path.rb +11 -1
  21. data/lib/grape/request.rb +12 -7
  22. data/lib/grape/router.rb +16 -7
  23. data/lib/grape/router/pattern.rb +17 -16
  24. data/lib/grape/router/route.rb +2 -2
  25. data/lib/grape/util/base_inheritable.rb +4 -0
  26. data/lib/grape/util/cache.rb +20 -0
  27. data/lib/grape/util/lazy_object.rb +43 -0
  28. data/lib/grape/util/reverse_stackable_values.rb +1 -1
  29. data/lib/grape/util/stackable_values.rb +6 -21
  30. data/lib/grape/validations/params_scope.rb +1 -1
  31. data/lib/grape/validations/types/file.rb +1 -0
  32. data/lib/grape/validations/types/primitive_coercer.rb +7 -4
  33. data/lib/grape/validations/validators/coerce.rb +1 -1
  34. data/lib/grape/validations/validators/exactly_one_of.rb +4 -2
  35. data/lib/grape/version.rb +1 -1
  36. data/spec/grape/api_spec.rb +7 -6
  37. data/spec/grape/exceptions/validation_errors_spec.rb +2 -2
  38. data/spec/grape/middleware/formatter_spec.rb +2 -2
  39. data/spec/grape/middleware/stack_spec.rb +9 -0
  40. data/spec/grape/validations/instance_behaivour_spec.rb +1 -1
  41. data/spec/grape/validations/types/primitive_coercer_spec.rb +75 -0
  42. data/spec/grape/validations/validators/coerce_spec.rb +15 -51
  43. data/spec/grape/validations/validators/exactly_one_of_spec.rb +12 -12
  44. data/spec/grape/validations_spec.rb +8 -12
  45. data/spec/spec_helper.rb +3 -0
  46. data/spec/support/eager_load.rb +19 -0
  47. metadata +12 -6
  48. data/lib/grape/util/content_types.rb +0 -28
@@ -935,7 +935,7 @@ XML
935
935
 
936
936
  it 'adds a before filter to current and child namespaces only' do
937
937
  subject.get '/' do
938
- "root - #{@foo}"
938
+ "root - #{instance_variable_defined?(:@foo) ? @foo : nil}"
939
939
  end
940
940
  subject.namespace :blah do
941
941
  before { @foo = 'foo' }
@@ -3677,12 +3677,13 @@ XML
3677
3677
  end
3678
3678
  end
3679
3679
  context ':serializable_hash' do
3680
- before(:each) do
3681
- class SerializableHashExample
3682
- def serializable_hash
3683
- { abc: 'def' }
3684
- end
3680
+ class SerializableHashExample
3681
+ def serializable_hash
3682
+ { abc: 'def' }
3685
3683
  end
3684
+ end
3685
+
3686
+ before(:each) do
3686
3687
  subject.format :serializable_hash
3687
3688
  end
3688
3689
  it 'instance' do
@@ -81,8 +81,8 @@ describe Grape::Exceptions::ValidationErrors do
81
81
  expect(last_response.status).to eq(400)
82
82
  expect(JSON.parse(last_response.body)).to eq(
83
83
  [
84
- 'params' => %w[beer wine juice],
85
- 'messages' => ['are missing, exactly one parameter must be provided']
84
+ 'params' => %w[beer wine],
85
+ 'messages' => ['are mutually exclusive']
86
86
  ]
87
87
  )
88
88
  end
@@ -402,10 +402,10 @@ describe Grape::Middleware::Formatter do
402
402
  let(:app) { ->(_env) { [200, {}, ['']] } }
403
403
  before do
404
404
  Grape::Formatter.register :invalid, InvalidFormatter
405
- Grape::ContentTypes::CONTENT_TYPES[:invalid] = 'application/x-invalid'
405
+ Grape::ContentTypes.register :invalid, 'application/x-invalid'
406
406
  end
407
407
  after do
408
- Grape::ContentTypes::CONTENT_TYPES.delete(:invalid)
408
+ Grape::ContentTypes.default_elements.delete(:invalid)
409
409
  Grape::Formatter.default_elements.delete(:invalid)
410
410
  end
411
411
 
@@ -111,6 +111,15 @@ describe Grape::Middleware::Stack do
111
111
  expect(subject[1]).to eq(StackSpec::BlockMiddleware)
112
112
  expect(subject[2]).to eq(StackSpec::BarMiddleware)
113
113
  end
114
+
115
+ context 'middleware spec with proc declaration exists' do
116
+ let(:middleware_spec_with_proc) { [:use, StackSpec::FooMiddleware, proc] }
117
+
118
+ it 'properly forwards spec arguments' do
119
+ expect(subject).to receive(:use).with(StackSpec::FooMiddleware)
120
+ subject.merge_with([middleware_spec_with_proc])
121
+ end
122
+ end
114
123
  end
115
124
 
116
125
  describe '#build' do
@@ -6,7 +6,7 @@ describe 'Validator with instance variables' do
6
6
  let(:validator_type) do
7
7
  Class.new(Grape::Validations::Base) do
8
8
  def validate_param!(_attr_name, _params)
9
- if @instance_variable
9
+ if instance_variable_defined?(:@instance_variable) && @instance_variable
10
10
  raise Grape::Exceptions::Validation.new(params: ['params'],
11
11
  message: 'This should never happen')
12
12
  end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Grape::Validations::Types::PrimitiveCoercer do
6
+ let(:strict) { false }
7
+
8
+ subject { described_class.new(type, strict) }
9
+
10
+ describe '.call' do
11
+ context 'Boolean' do
12
+ let(:type) { Grape::API::Boolean }
13
+
14
+ [true, 'true', 1].each do |val|
15
+ it "coerces '#{val}' to true" do
16
+ expect(subject.call(val)).to eq(true)
17
+ end
18
+ end
19
+
20
+ [false, 'false', 0].each do |val|
21
+ it "coerces '#{val}' to false" do
22
+ expect(subject.call(val)).to eq(false)
23
+ end
24
+ end
25
+
26
+ it 'returns an error when the given value cannot be coerced' do
27
+ expect(subject.call(123)).to be_instance_of(Grape::Validations::Types::InvalidValue)
28
+ end
29
+ end
30
+
31
+ context 'String' do
32
+ let(:type) { String }
33
+
34
+ it 'coerces to String' do
35
+ expect(subject.call(10)).to eq('10')
36
+ end
37
+ end
38
+
39
+ context 'BigDecimal' do
40
+ let(:type) { BigDecimal }
41
+
42
+ it 'coerces to BigDecimal' do
43
+ expect(subject.call(5)).to eq(BigDecimal(5))
44
+ end
45
+ end
46
+
47
+ context 'the strict mode' do
48
+ let(:strict) { true }
49
+
50
+ context 'Boolean' do
51
+ let(:type) { Grape::API::Boolean }
52
+
53
+ it 'returns an error when the given value is not Boolean' do
54
+ expect(subject.call(1)).to be_instance_of(Grape::Validations::Types::InvalidValue)
55
+ end
56
+
57
+ it 'returns a value as it is when the given value is Boolean' do
58
+ expect(subject.call(true)).to eq(true)
59
+ end
60
+ end
61
+
62
+ context 'BigDecimal' do
63
+ let(:type) { BigDecimal }
64
+
65
+ it 'returns an error when the given value is not BigDecimal' do
66
+ expect(subject.call(1)).to be_instance_of(Grape::Validations::Types::InvalidValue)
67
+ end
68
+
69
+ it 'returns a value as it is when the given value is BigDecimal' do
70
+ expect(subject.call(BigDecimal(0))).to eq(BigDecimal(0))
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -154,6 +154,19 @@ describe Grape::Validations::CoerceValidator do
154
154
  end
155
155
 
156
156
  context 'coerces' do
157
+ it 'BigDecimal' do
158
+ subject.params do
159
+ requires :bigdecimal, coerce: BigDecimal
160
+ end
161
+ subject.get '/bigdecimal' do
162
+ params[:bigdecimal].class
163
+ end
164
+
165
+ get '/bigdecimal', bigdecimal: '45'
166
+ expect(last_response.status).to eq(200)
167
+ expect(last_response.body).to eq('BigDecimal')
168
+ end
169
+
157
170
  it 'Integer' do
158
171
  subject.params do
159
172
  requires :int, coerce: Integer
@@ -281,66 +294,17 @@ describe Grape::Validations::CoerceValidator do
281
294
  end
282
295
  end
283
296
 
284
- it 'Bool' do
285
- subject.params do
286
- requires :bool, coerce: Grape::API::Boolean
287
- end
288
- subject.get '/bool' do
289
- params[:bool].class
290
- end
291
-
292
- get '/bool', bool: 1
293
- expect(last_response.status).to eq(200)
294
- expect(last_response.body).to eq('TrueClass')
295
-
296
- get '/bool', bool: 0
297
- expect(last_response.status).to eq(200)
298
- expect(last_response.body).to eq('FalseClass')
299
-
300
- get '/bool', bool: 'false'
301
- expect(last_response.status).to eq(200)
302
- expect(last_response.body).to eq('FalseClass')
303
-
304
- get '/bool', bool: 'true'
305
- expect(last_response.status).to eq(200)
306
- expect(last_response.body).to eq('TrueClass')
307
- end
308
-
309
297
  it 'Boolean' do
310
298
  subject.params do
311
- optional :boolean, type: Boolean, default: true
299
+ requires :boolean, type: Boolean
312
300
  end
313
301
  subject.get '/boolean' do
314
302
  params[:boolean].class
315
303
  end
316
304
 
317
- get '/boolean'
318
- expect(last_response.status).to eq(200)
319
- expect(last_response.body).to eq('TrueClass')
320
-
321
- get '/boolean', boolean: true
322
- expect(last_response.status).to eq(200)
323
- expect(last_response.body).to eq('TrueClass')
324
-
325
- get '/boolean', boolean: false
326
- expect(last_response.status).to eq(200)
327
- expect(last_response.body).to eq('FalseClass')
328
-
329
- get '/boolean', boolean: 'true'
305
+ get '/boolean', boolean: 1
330
306
  expect(last_response.status).to eq(200)
331
307
  expect(last_response.body).to eq('TrueClass')
332
-
333
- get '/boolean', boolean: 'false'
334
- expect(last_response.status).to eq(200)
335
- expect(last_response.body).to eq('FalseClass')
336
-
337
- get '/boolean', boolean: 123
338
- expect(last_response.status).to eq(400)
339
- expect(last_response.body).to eq('boolean is invalid')
340
-
341
- get '/boolean', boolean: '123'
342
- expect(last_response.status).to eq(400)
343
- expect(last_response.body).to eq('boolean is invalid')
344
308
  end
345
309
 
346
310
  it 'Rack::Multipart::UploadedFile' do
@@ -100,7 +100,7 @@ describe Grape::Validations::ExactlyOneOfValidator do
100
100
  validate
101
101
  expect(last_response.status).to eq 400
102
102
  expect(JSON.parse(last_response.body)).to eq(
103
- 'beer,wine,grapefruit' => ['are missing, exactly one parameter must be provided']
103
+ 'beer,wine,grapefruit' => ['are mutually exclusive']
104
104
  )
105
105
  end
106
106
 
@@ -112,7 +112,7 @@ describe Grape::Validations::ExactlyOneOfValidator do
112
112
  validate
113
113
  expect(last_response.status).to eq 400
114
114
  expect(JSON.parse(last_response.body)).to eq(
115
- 'beer,wine,grapefruit' => ['are missing, exactly one parameter must be provided']
115
+ 'beer,wine,grapefruit' => ['are mutually exclusive']
116
116
  )
117
117
  end
118
118
  end
@@ -126,7 +126,7 @@ describe Grape::Validations::ExactlyOneOfValidator do
126
126
  validate
127
127
  expect(last_response.status).to eq 400
128
128
  expect(JSON.parse(last_response.body)).to eq(
129
- 'beer,wine,grapefruit' => ['are missing, exactly one parameter must be provided']
129
+ 'beer,grapefruit' => ['are mutually exclusive']
130
130
  )
131
131
  end
132
132
  end
@@ -139,7 +139,7 @@ describe Grape::Validations::ExactlyOneOfValidator do
139
139
  validate
140
140
  expect(last_response.status).to eq 400
141
141
  expect(JSON.parse(last_response.body)).to eq(
142
- 'beer,wine,grapefruit' => ['you should choose one']
142
+ 'beer,wine' => ['you should choose one']
143
143
  )
144
144
  end
145
145
  end
@@ -175,7 +175,7 @@ describe Grape::Validations::ExactlyOneOfValidator do
175
175
  validate
176
176
  expect(last_response.status).to eq 400
177
177
  expect(JSON.parse(last_response.body)).to eq(
178
- 'item[beer],item[wine],item[grapefruit]' => ['are missing, exactly one parameter must be provided']
178
+ 'item[beer],item[wine]' => ['are mutually exclusive']
179
179
  )
180
180
  end
181
181
  end
@@ -190,7 +190,7 @@ describe Grape::Validations::ExactlyOneOfValidator do
190
190
  validate
191
191
  expect(last_response.status).to eq 400
192
192
  expect(JSON.parse(last_response.body)).to eq(
193
- 'item[beer],item[wine],item[grapefruit]' => ['are missing, exactly one parameter must be provided']
193
+ 'item[beer],item[wine]' => ['are mutually exclusive']
194
194
  )
195
195
  end
196
196
  end
@@ -213,11 +213,11 @@ describe Grape::Validations::ExactlyOneOfValidator do
213
213
  validate
214
214
  expect(last_response.status).to eq 400
215
215
  expect(JSON.parse(last_response.body)).to eq(
216
- 'items[0][beer],items[0][wine],items[0][grapefruit]' => [
217
- 'are missing, exactly one parameter must be provided'
216
+ 'items[0][beer],items[0][wine]' => [
217
+ 'are mutually exclusive'
218
218
  ],
219
- 'items[1][beer],items[1][wine],items[1][grapefruit]' => [
220
- 'are missing, exactly one parameter must be provided'
219
+ 'items[1][wine],items[1][grapefruit]' => [
220
+ 'are mutually exclusive'
221
221
  ]
222
222
  )
223
223
  end
@@ -231,8 +231,8 @@ describe Grape::Validations::ExactlyOneOfValidator do
231
231
  validate
232
232
  expect(last_response.status).to eq 400
233
233
  expect(JSON.parse(last_response.body)).to eq(
234
- 'items[0][nested_items][0][beer],items[0][nested_items][0][wine],items[0][nested_items][0][grapefruit]' => [
235
- 'are missing, exactly one parameter must be provided'
234
+ 'items[0][nested_items][0][beer],items[0][nested_items][0][wine]' => [
235
+ 'are mutually exclusive'
236
236
  ]
237
237
  )
238
238
  end
@@ -11,14 +11,17 @@ describe Grape::Validations do
11
11
 
12
12
  describe 'params' do
13
13
  context 'optional' do
14
- it 'validates when params is present' do
14
+ before do
15
15
  subject.params do
16
16
  optional :a_number, regexp: /^[0-9]+$/
17
+ optional :attachment, type: File
17
18
  end
18
19
  subject.get '/optional' do
19
20
  'optional works!'
20
21
  end
22
+ end
21
23
 
24
+ it 'validates when params is present' do
22
25
  get '/optional', a_number: 'string'
23
26
  expect(last_response.status).to eq(400)
24
27
  expect(last_response.body).to eq('a_number is invalid')
@@ -29,14 +32,7 @@ describe Grape::Validations do
29
32
  end
30
33
 
31
34
  it "doesn't validate when param not present" do
32
- subject.params do
33
- optional :a_number, regexp: /^[0-9]+$/
34
- end
35
- subject.get '/optional' do
36
- 'optional works!'
37
- end
38
-
39
- get '/optional'
35
+ get '/optional', a_number: nil, attachment: nil
40
36
  expect(last_response.status).to eq(200)
41
37
  expect(last_response.body).to eq('optional works!')
42
38
  end
@@ -1422,7 +1418,7 @@ describe Grape::Validations do
1422
1418
  it 'errors when two or more are present' do
1423
1419
  get '/custom_message/exactly_one_of', beer: 'string', wine: 'anotherstring'
1424
1420
  expect(last_response.status).to eq(400)
1425
- expect(last_response.body).to eq 'beer, wine, juice are missing, exactly one parameter is required'
1421
+ expect(last_response.body).to eq 'beer, wine are missing, exactly one parameter is required'
1426
1422
  end
1427
1423
  end
1428
1424
 
@@ -1441,7 +1437,7 @@ describe Grape::Validations do
1441
1437
  it 'errors when two or more are present' do
1442
1438
  get '/exactly_one_of', beer: 'string', wine: 'anotherstring'
1443
1439
  expect(last_response.status).to eq(400)
1444
- expect(last_response.body).to eq 'beer, wine, juice are missing, exactly one parameter must be provided'
1440
+ expect(last_response.body).to eq 'beer, wine are mutually exclusive'
1445
1441
  end
1446
1442
  end
1447
1443
 
@@ -1481,7 +1477,7 @@ describe Grape::Validations do
1481
1477
  it 'errors when two or more are present' do
1482
1478
  get '/exactly_one_of_nested', nested: { beer_nested: 'string' }, nested2: [{ beer_nested2: 'string', wine_nested2: 'anotherstring' }]
1483
1479
  expect(last_response.status).to eq(400)
1484
- expect(last_response.body).to eq 'nested2[0][beer_nested2], nested2[0][wine_nested2], nested2[0][juice_nested2] are missing, exactly one parameter must be provided'
1480
+ expect(last_response.body).to eq 'nested2[0][beer_nested2], nested2[0][wine_nested2] are mutually exclusive'
1485
1481
  end
1486
1482
  end
1487
1483
  end
@@ -14,6 +14,8 @@ Dir["#{File.dirname(__FILE__)}/support/*.rb"].each do |file|
14
14
  require file
15
15
  end
16
16
 
17
+ eager_load!
18
+
17
19
  # The default value for this setting is true in a standard Rails app,
18
20
  # so it should be set to true here as well to reflect that.
19
21
  I18n.enforce_available_locales = true
@@ -33,6 +35,7 @@ RSpec.configure do |config|
33
35
  config.include Spec::Support::Helpers
34
36
  config.raise_errors_for_deprecations!
35
37
  config.filter_run_when_matching :focus
38
+ config.warnings = true
36
39
 
37
40
  config.before(:each) { Grape::Util::InheritableSetting.reset_global! }
38
41
 
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Grape uses autoload https://api.rubyonrails.org/classes/ActiveSupport/Autoload.html.
4
+ # When a class/module get added to the list, ActiveSupport doesn't check whether it really exists.
5
+ # This method loads all classes/modules defined via autoload to be sure only existing
6
+ # classes/modules were listed.
7
+ def eager_load!(scope = Grape)
8
+ # get modules
9
+ scope.constants.each do |const_name|
10
+ const = scope.const_get(const_name)
11
+
12
+ next unless const.respond_to?(:eager_load!)
13
+
14
+ const.eager_load!
15
+
16
+ # check its modules, they might need to be loaded as well.
17
+ eager_load!(const)
18
+ end
19
+ end
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.3.0
4
+ version: 1.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Bleigh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-11 00:00:00.000000000 Z
11
+ date: 2020-03-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -113,6 +113,7 @@ files:
113
113
  - lib/grape/api/helpers.rb
114
114
  - lib/grape/api/instance.rb
115
115
  - lib/grape/config.rb
116
+ - lib/grape/content_types.rb
116
117
  - lib/grape/cookies.rb
117
118
  - lib/grape/dsl/api.rb
118
119
  - lib/grape/dsl/callbacks.rb
@@ -200,13 +201,14 @@ files:
200
201
  - lib/grape/serve_file/file_response.rb
201
202
  - lib/grape/serve_file/sendfile_response.rb
202
203
  - lib/grape/util/base_inheritable.rb
203
- - lib/grape/util/content_types.rb
204
+ - lib/grape/util/cache.rb
204
205
  - lib/grape/util/endpoint_configuration.rb
205
206
  - lib/grape/util/env.rb
206
207
  - lib/grape/util/inheritable_setting.rb
207
208
  - lib/grape/util/inheritable_values.rb
208
209
  - lib/grape/util/json.rb
209
210
  - lib/grape/util/lazy_block.rb
211
+ - lib/grape/util/lazy_object.rb
210
212
  - lib/grape/util/lazy_value.rb
211
213
  - lib/grape/util/registrable.rb
212
214
  - lib/grape/util/reverse_stackable_values.rb
@@ -330,6 +332,7 @@ files:
330
332
  - spec/grape/validations/multiple_attributes_iterator_spec.rb
331
333
  - spec/grape/validations/params_scope_spec.rb
332
334
  - spec/grape/validations/single_attribute_iterator_spec.rb
335
+ - spec/grape/validations/types/primitive_coercer_spec.rb
333
336
  - spec/grape/validations/types_spec.rb
334
337
  - spec/grape/validations/validators/all_or_none_spec.rb
335
338
  - spec/grape/validations/validators/allow_blank_spec.rb
@@ -351,6 +354,7 @@ files:
351
354
  - spec/spec_helper.rb
352
355
  - spec/support/basic_auth_encode_helpers.rb
353
356
  - spec/support/content_type_helpers.rb
357
+ - spec/support/eager_load.rb
354
358
  - spec/support/endpoint_faker.rb
355
359
  - spec/support/file_streamer.rb
356
360
  - spec/support/integer_helpers.rb
@@ -360,9 +364,9 @@ licenses:
360
364
  - MIT
361
365
  metadata:
362
366
  bug_tracker_uri: https://github.com/ruby-grape/grape/issues
363
- changelog_uri: https://github.com/ruby-grape/grape/blob/v1.3.0/CHANGELOG.md
364
- documentation_uri: https://www.rubydoc.info/gems/grape/1.3.0
365
- source_code_uri: https://github.com/ruby-grape/grape/tree/v1.3.0
367
+ changelog_uri: https://github.com/ruby-grape/grape/blob/v1.3.1/CHANGELOG.md
368
+ documentation_uri: https://www.rubydoc.info/gems/grape/1.3.1
369
+ source_code_uri: https://github.com/ruby-grape/grape/tree/v1.3.1
366
370
  post_install_message:
367
371
  rdoc_options: []
368
372
  require_paths:
@@ -386,6 +390,7 @@ test_files:
386
390
  - spec/shared/versioning_examples.rb
387
391
  - spec/support/versioned_helpers.rb
388
392
  - spec/support/content_type_helpers.rb
393
+ - spec/support/eager_load.rb
389
394
  - spec/support/basic_auth_encode_helpers.rb
390
395
  - spec/support/file_streamer.rb
391
396
  - spec/support/endpoint_faker.rb
@@ -410,6 +415,7 @@ test_files:
410
415
  - spec/grape/api_remount_spec.rb
411
416
  - spec/grape/validations/types_spec.rb
412
417
  - spec/grape/validations/attributes_iterator_spec.rb
418
+ - spec/grape/validations/types/primitive_coercer_spec.rb
413
419
  - spec/grape/validations/validators/regexp_spec.rb
414
420
  - spec/grape/validations/validators/default_spec.rb
415
421
  - spec/grape/validations/validators/values_spec.rb