grape 1.3.0 → 1.3.2

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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +38 -0
  3. data/README.md +4 -6
  4. data/UPGRADING.md +61 -16
  5. data/lib/grape/api/instance.rb +11 -7
  6. data/lib/grape/api.rb +2 -2
  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 +26 -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 +4 -4
  18. data/lib/grape/middleware/versioner/parse_media_type_patch.rb +2 -1
  19. data/lib/grape/middleware/versioner/path.rb +1 -1
  20. data/lib/grape/namespace.rb +12 -2
  21. data/lib/grape/path.rb +13 -3
  22. data/lib/grape/request.rb +12 -7
  23. data/lib/grape/router/pattern.rb +17 -16
  24. data/lib/grape/router/route.rb +4 -5
  25. data/lib/grape/router.rb +24 -14
  26. data/lib/grape/util/base_inheritable.rb +13 -6
  27. data/lib/grape/util/cache.rb +20 -0
  28. data/lib/grape/util/lazy_object.rb +43 -0
  29. data/lib/grape/util/reverse_stackable_values.rb +2 -0
  30. data/lib/grape/util/stackable_values.rb +7 -20
  31. data/lib/grape/validations/params_scope.rb +1 -1
  32. data/lib/grape/validations/types/build_coercer.rb +4 -3
  33. data/lib/grape/validations/types/custom_type_coercer.rb +1 -1
  34. data/lib/grape/validations/types/file.rb +15 -12
  35. data/lib/grape/validations/types/json.rb +40 -36
  36. data/lib/grape/validations/types/primitive_coercer.rb +6 -3
  37. data/lib/grape/validations/types.rb +6 -5
  38. data/lib/grape/validations/validators/coerce.rb +14 -12
  39. data/lib/grape/validations/validators/exactly_one_of.rb +4 -2
  40. data/lib/grape/validations/validators/regexp.rb +1 -1
  41. data/lib/grape/version.rb +1 -1
  42. data/lib/grape.rb +2 -3
  43. data/spec/grape/api_spec.rb +7 -6
  44. data/spec/grape/exceptions/validation_errors_spec.rb +2 -2
  45. data/spec/grape/middleware/formatter_spec.rb +2 -2
  46. data/spec/grape/middleware/stack_spec.rb +9 -0
  47. data/spec/grape/path_spec.rb +4 -4
  48. data/spec/grape/validations/instance_behaivour_spec.rb +1 -1
  49. data/spec/grape/validations/types/primitive_coercer_spec.rb +75 -0
  50. data/spec/grape/validations/types_spec.rb +1 -1
  51. data/spec/grape/validations/validators/coerce_spec.rb +160 -78
  52. data/spec/grape/validations/validators/exactly_one_of_spec.rb +12 -12
  53. data/spec/grape/validations_spec.rb +8 -12
  54. data/spec/spec_helper.rb +3 -0
  55. data/spec/support/eager_load.rb +19 -0
  56. metadata +12 -6
  57. data/lib/grape/util/content_types.rb +0 -28
@@ -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
data/spec/spec_helper.rb CHANGED
@@ -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.2
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-04-12 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.2/CHANGELOG.md
368
+ documentation_uri: https://www.rubydoc.info/gems/grape/1.3.2
369
+ source_code_uri: https://github.com/ruby-grape/grape/tree/v1.3.2
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
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Grape
4
- module ContentTypes
5
- # Content types are listed in order of preference.
6
- CONTENT_TYPES = { # rubocop:disable Style/MutableConstant
7
- xml: 'application/xml',
8
- serializable_hash: 'application/json',
9
- json: 'application/json',
10
- binary: 'application/octet-stream',
11
- txt: 'text/plain'
12
- }
13
-
14
- def self.content_types_for_settings(settings)
15
- return if settings.blank?
16
-
17
- settings.each_with_object({}) { |value, result| result.merge!(value) }
18
- end
19
-
20
- def self.content_types_for(from_settings)
21
- if from_settings.present?
22
- from_settings
23
- else
24
- Grape::ContentTypes::CONTENT_TYPES
25
- end
26
- end
27
- end
28
- end