grape 1.7.1 → 1.8.0
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 +22 -1
- data/CONTRIBUTING.md +1 -1
- data/README.md +12 -4
- data/grape.gemspec +2 -2
- data/lib/grape/api.rb +2 -2
- data/lib/grape/content_types.rb +2 -8
- data/lib/grape/dsl/desc.rb +1 -1
- data/lib/grape/dsl/inside_route.rb +5 -5
- data/lib/grape/dsl/request_response.rb +2 -1
- data/lib/grape/dsl/settings.rb +2 -6
- data/lib/grape/endpoint.rb +19 -17
- data/lib/grape/error_formatter/base.rb +1 -1
- data/lib/grape/exceptions/base.rb +2 -2
- data/lib/grape/exceptions/missing_group_type.rb +1 -6
- data/lib/grape/exceptions/unsupported_group_type.rb +1 -6
- data/lib/grape/exceptions/validation_errors.rb +1 -6
- data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +3 -3
- data/lib/grape/extensions/hash.rb +4 -7
- data/lib/grape/extensions/hashie/mash.rb +3 -3
- data/lib/grape/formatter/serializable_hash.rb +7 -7
- data/lib/grape/middleware/auth/base.rb +1 -1
- data/lib/grape/middleware/error.rb +1 -1
- data/lib/grape/middleware/formatter.rb +1 -1
- data/lib/grape/middleware/versioner/header.rb +11 -19
- data/lib/grape/router/route.rb +1 -3
- data/lib/grape/util/lazy_value.rb +3 -11
- data/lib/grape/util/strict_hash_configuration.rb +3 -4
- data/lib/grape/validations/multiple_attributes_iterator.rb +1 -1
- data/lib/grape/validations/params_scope.rb +8 -2
- data/lib/grape/validations/single_attribute_iterator.rb +3 -1
- data/lib/grape/validations/types/custom_type_coercer.rb +2 -16
- data/lib/grape/validations/validators/base.rb +9 -20
- data/lib/grape/validations/validators/default_validator.rb +2 -20
- data/lib/grape/validations/validators/multiple_params_base.rb +4 -8
- data/lib/grape/validations/validators/values_validator.rb +14 -5
- data/lib/grape/version.rb +1 -1
- data/lib/grape.rb +11 -3
- data/spec/grape/api/custom_validations_spec.rb +14 -57
- data/spec/grape/api_remount_spec.rb +36 -0
- data/spec/grape/api_spec.rb +10 -1
- data/spec/grape/dsl/desc_spec.rb +84 -87
- data/spec/grape/dsl/inside_route_spec.rb +6 -10
- data/spec/grape/dsl/request_response_spec.rb +21 -2
- data/spec/grape/endpoint_spec.rb +8 -8
- data/spec/grape/exceptions/body_parse_errors_spec.rb +40 -0
- data/spec/grape/exceptions/missing_group_type_spec.rb +5 -9
- data/spec/grape/exceptions/unsupported_group_type_spec.rb +5 -9
- data/spec/grape/grape_spec.rb +9 -0
- data/spec/grape/middleware/formatter_spec.rb +1 -1
- data/spec/grape/request_spec.rb +4 -14
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +6 -8
- data/spec/grape/validations/single_attribute_iterator_spec.rb +8 -9
- data/spec/grape/validations/validators/base_spec.rb +38 -0
- data/spec/grape/validations/validators/values_spec.rb +37 -0
- data/spec/grape/validations_spec.rb +7 -6
- data/spec/shared/deprecated_class_examples.rb +16 -0
- metadata +17 -22
- data/lib/grape/config.rb +0 -34
- data/lib/grape/extensions/deep_mergeable_hash.rb +0 -21
- data/lib/grape/extensions/deep_symbolize_hash.rb +0 -32
- data/spec/grape/config_spec.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ac7bd232782ed265b59ec7f4ea0dec03a0896b328694ebe1507cf9680e1bee41
|
4
|
+
data.tar.gz: b81cb45c2b6daab5b413af0df615a542907c9fbf1732e3fc46347321dedc4f65
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1929a95447ec3923443e908a8240195e7e4a0f5a3113f8679e947cc3813e800f45f35c928dfef9495ff277a983bf3bdcb4ca358ab889e28224d890a3d078d7de
|
7
|
+
data.tar.gz: 4d5141c1f331ee07eaa78bd89e1b76f99b6cbcb7d6f0dda3f12f9e6b900c977c9a0757c0d912a6cd53ea5ef9bce8409a211c4a77c4b78a0f5e607ecd1e055480
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,25 @@
|
|
1
|
-
### 1.
|
1
|
+
### 1.8.0 (2023/08/30)
|
2
|
+
|
3
|
+
#### Features
|
4
|
+
|
5
|
+
* [#2326](https://github.com/ruby-grape/grape/pull/2326): Use ActiveSupport extensions - [@ericproulx](https://github.com/ericproulx).
|
6
|
+
* [#2327](https://github.com/ruby-grape/grape/pull/2327): Use ActiveSupport deprecation - [@ericproulx](https://github.com/ericproulx).
|
7
|
+
* [#2330](https://github.com/ruby-grape/grape/pull/2330): Use ActiveSupport inflector - [@ericproulx](https://github.com/ericproulx).
|
8
|
+
* [#2331](https://github.com/ruby-grape/grape/pull/2331): Memory optimization when running validators - [@ericproulx](https://github.com/ericproulx).
|
9
|
+
* [#2332](https://github.com/ruby-grape/grape/pull/2332): Use ActiveSupport configurable - [@ericproulx](https://github.com/ericproulx).
|
10
|
+
* [#2333](https://github.com/ruby-grape/grape/pull/2333): Use custom messages in parameter validation with arity 1 - [@thedevjoao](https://github.com/TheDevJoao).
|
11
|
+
* [#2341](https://github.com/ruby-grape/grape/pull/2341): Stop yielding skip value - [@ericproulx](https://github.com/ericproulx).
|
12
|
+
* [#2342](https://github.com/ruby-grape/grape/pull/2342): Allow specifying a handler for grape_exceptions - [@mscrivo](https://github.com/mscrivo).
|
13
|
+
* [#2338](https://github.com/ruby-grape/grape/pull/2338): Fix unknown validator when using requires/optional with entity - [@mscrivo](https://github.com/mscrivo).
|
14
|
+
|
15
|
+
#### Fixes
|
16
|
+
|
17
|
+
* [#2339](https://github.com/ruby-grape/grape/pull/2339): Documentation and specs for remountable configuration in params - [@myxoh](https://github.com/myxoh).
|
18
|
+
* [#2328](https://github.com/ruby-grape/grape/pull/2328): Don't cache Class.instance_methods - [@byroot](https://github.com/byroot).
|
19
|
+
* [#2337](https://github.com/ruby-grape/grape/pull/2337): Fix: allow custom validators that do not end with _validator - [@ericproulx](https://github.com/ericproulx).
|
20
|
+
* [#2346](https://github.com/ruby-grape/grape/pull/2346): Adjust test expectations to conform to rack 3 - [@kbarrette](https://github.com/kbarrette).
|
21
|
+
|
22
|
+
## 1.7.1 (2023/05/14)
|
2
23
|
|
3
24
|
#### Features
|
4
25
|
|
data/CONTRIBUTING.md
CHANGED
@@ -145,7 +145,7 @@ git push origin my-feature-branch -f
|
|
145
145
|
|
146
146
|
#### Check on Your Pull Request
|
147
147
|
|
148
|
-
Go back to your pull request after a few minutes and see whether it passed muster with
|
148
|
+
Go back to your pull request after a few minutes and see whether it passed muster with CI. Everything should look green, otherwise fix issues and amend your commit as described above.
|
149
149
|
|
150
150
|
#### Be Patient
|
151
151
|
|
data/README.md
CHANGED
@@ -159,7 +159,7 @@ content negotiation, versioning and much more.
|
|
159
159
|
|
160
160
|
## Stable Release
|
161
161
|
|
162
|
-
You're reading the documentation for the stable release of Grape, 1.
|
162
|
+
You're reading the documentation for the stable release of Grape, **1.8.0**.
|
163
163
|
Please read [UPGRADING](UPGRADING.md) when upgrading from a previous version.
|
164
164
|
|
165
165
|
## Project Resources
|
@@ -524,15 +524,15 @@ end
|
|
524
524
|
```ruby
|
525
525
|
class BasicAPI < Grape::API
|
526
526
|
desc 'Statuses index' do
|
527
|
-
params:
|
527
|
+
params: (configuration[:entity] || API::Entities::Status).documentation
|
528
528
|
end
|
529
529
|
params do
|
530
|
-
requires :all, using:
|
530
|
+
requires :all, using: (configuration[:entity] || API::Entities::Status).documentation
|
531
531
|
end
|
532
532
|
get '/statuses' do
|
533
533
|
statuses = Status.all
|
534
534
|
type = current_user.admin? ? :full : :default
|
535
|
-
present statuses, with:
|
535
|
+
present statuses, with: (configuration[:entity] || API::Entities::Status), type: type
|
536
536
|
end
|
537
537
|
end
|
538
538
|
|
@@ -2624,6 +2624,14 @@ class Twitter::API < Grape::API
|
|
2624
2624
|
end
|
2625
2625
|
```
|
2626
2626
|
|
2627
|
+
If you want to customize the shape of grape exceptions returned to the user, to match your `:all` handler for example, you can pass a block to `rescue_from :grape_exceptions`.
|
2628
|
+
|
2629
|
+
```ruby
|
2630
|
+
rescue_from :grape_exceptions do |e|
|
2631
|
+
error!(e, e.status)
|
2632
|
+
end
|
2633
|
+
```
|
2634
|
+
|
2627
2635
|
You can also rescue specific exceptions.
|
2628
2636
|
|
2629
2637
|
```ruby
|
data/grape.gemspec
CHANGED
@@ -20,11 +20,11 @@ Gem::Specification.new do |s|
|
|
20
20
|
'source_code_uri' => "https://github.com/ruby-grape/grape/tree/v#{s.version}"
|
21
21
|
}
|
22
22
|
|
23
|
-
s.add_runtime_dependency 'activesupport'
|
23
|
+
s.add_runtime_dependency 'activesupport', '>= 5'
|
24
24
|
s.add_runtime_dependency 'builder'
|
25
25
|
s.add_runtime_dependency 'dry-types', '>= 1.1'
|
26
26
|
s.add_runtime_dependency 'mustermann-grape', '~> 1.0.0'
|
27
|
-
s.add_runtime_dependency 'rack', '>= 1.3.0'
|
27
|
+
s.add_runtime_dependency 'rack', '>= 1.3.0'
|
28
28
|
s.add_runtime_dependency 'rack-accept'
|
29
29
|
|
30
30
|
s.files = %w[CHANGELOG.md CONTRIBUTING.md README.md grape.png UPGRADING.md LICENSE]
|
data/lib/grape/api.rb
CHANGED
@@ -8,7 +8,7 @@ module Grape
|
|
8
8
|
# should subclass this class in order to build an API.
|
9
9
|
class API
|
10
10
|
# Class methods that we want to call on the API rather than on the API object
|
11
|
-
NON_OVERRIDABLE =
|
11
|
+
NON_OVERRIDABLE = %i[call call! configuration compile! inherited].freeze
|
12
12
|
|
13
13
|
class Boolean
|
14
14
|
def self.build(val)
|
@@ -50,7 +50,7 @@ module Grape
|
|
50
50
|
|
51
51
|
# Redefines all methods so that are forwarded to add_setup and be recorded
|
52
52
|
def override_all_methods!
|
53
|
-
(base_instance.methods - NON_OVERRIDABLE).each do |method_override|
|
53
|
+
(base_instance.methods - Class.methods - NON_OVERRIDABLE).each do |method_override|
|
54
54
|
define_singleton_method(method_override) do |*args, &block|
|
55
55
|
add_setup(method_override, *args, &block)
|
56
56
|
end
|
data/lib/grape/content_types.rb
CHANGED
@@ -17,17 +17,11 @@ module Grape
|
|
17
17
|
|
18
18
|
class << self
|
19
19
|
def content_types_for_settings(settings)
|
20
|
-
|
21
|
-
|
22
|
-
settings.each_with_object({}) { |value, result| result.merge!(value) }
|
20
|
+
settings&.inject(:merge!)
|
23
21
|
end
|
24
22
|
|
25
23
|
def content_types_for(from_settings)
|
26
|
-
|
27
|
-
from_settings
|
28
|
-
else
|
29
|
-
Grape::ContentTypes::CONTENT_TYPES.merge(default_elements)
|
30
|
-
end
|
24
|
+
from_settings.presence || Grape::ContentTypes::CONTENT_TYPES.merge(default_elements)
|
31
25
|
end
|
32
26
|
end
|
33
27
|
end
|
data/lib/grape/dsl/desc.rb
CHANGED
@@ -68,7 +68,7 @@ module Grape
|
|
68
68
|
end
|
69
69
|
|
70
70
|
config_class.configure(&config_block)
|
71
|
-
warn
|
71
|
+
ActiveSupport::Deprecation.warn('Passing a options hash and a block to `desc` is deprecated. Move all hash options to block.') if options.any?
|
72
72
|
options = config_class.settings
|
73
73
|
else
|
74
74
|
options = options.merge(description: description)
|
@@ -103,7 +103,7 @@ module Grape
|
|
103
103
|
|
104
104
|
if type == 'Hash' && !has_children
|
105
105
|
{}
|
106
|
-
elsif type == 'Array' || (type&.start_with?('[') &&
|
106
|
+
elsif type == 'Array' || (type&.start_with?('[') && type&.exclude?(','))
|
107
107
|
[]
|
108
108
|
elsif type == 'Set' || type&.start_with?('#<Set')
|
109
109
|
Set.new
|
@@ -280,13 +280,13 @@ module Grape
|
|
280
280
|
# Deprecated method to send files to the client. Use `sendfile` or `stream`
|
281
281
|
def file(value = nil)
|
282
282
|
if value.is_a?(String)
|
283
|
-
warn
|
283
|
+
ActiveSupport::Deprecation.warn('Use sendfile or stream to send files.')
|
284
284
|
sendfile(value)
|
285
285
|
elsif !value.is_a?(NilClass)
|
286
|
-
warn
|
286
|
+
ActiveSupport::Deprecation.warn('Use stream to use a Stream object.')
|
287
287
|
stream(value)
|
288
288
|
else
|
289
|
-
warn
|
289
|
+
ActiveSupport::Deprecation.warn('Use sendfile or stream to send files.')
|
290
290
|
sendfile
|
291
291
|
end
|
292
292
|
end
|
@@ -433,7 +433,7 @@ module Grape
|
|
433
433
|
# the given entity_class.
|
434
434
|
def entity_representation_for(entity_class, object, options)
|
435
435
|
embeds = { env: env }
|
436
|
-
embeds[:version] = env[Grape::Env::API_VERSION] if env
|
436
|
+
embeds[:version] = env[Grape::Env::API_VERSION] if env.key?(Grape::Env::API_VERSION)
|
437
437
|
entity_class.represent(object, **embeds.merge(options))
|
438
438
|
end
|
439
439
|
end
|
@@ -112,10 +112,11 @@ module Grape
|
|
112
112
|
|
113
113
|
if args.include?(:all)
|
114
114
|
namespace_inheritable(:rescue_all, true)
|
115
|
-
namespace_inheritable
|
115
|
+
namespace_inheritable(:all_rescue_handler, handler)
|
116
116
|
elsif args.include?(:grape_exceptions)
|
117
117
|
namespace_inheritable(:rescue_all, true)
|
118
118
|
namespace_inheritable(:rescue_grape_exceptions, true)
|
119
|
+
namespace_inheritable(:grape_exceptions_rescue_handler, handler)
|
119
120
|
else
|
120
121
|
handler_type =
|
121
122
|
case options[:rescue_subclasses]
|
data/lib/grape/dsl/settings.rb
CHANGED
@@ -109,13 +109,9 @@ module Grape
|
|
109
109
|
settings = get_or_set :namespace_reverse_stackable, key, nil
|
110
110
|
return if settings.blank?
|
111
111
|
|
112
|
-
|
113
|
-
|
114
|
-
setting.each do |field, value|
|
115
|
-
result[field] ||= value
|
116
|
-
end
|
112
|
+
settings.each_with_object({}) do |setting, result|
|
113
|
+
result.merge!(setting) { |_k, s1, _s2| s1 }
|
117
114
|
end
|
118
|
-
result
|
119
115
|
end
|
120
116
|
|
121
117
|
# (see #unset_global_setting)
|
data/lib/grape/endpoint.rb
CHANGED
@@ -171,10 +171,9 @@ module Grape
|
|
171
171
|
end
|
172
172
|
|
173
173
|
def prepare_routes_requirements
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
base_requirements.merge!(single_requirements)
|
174
|
+
{}.merge!(*namespace_stackable(:namespace).map(&:requirements)).tap do |requirements|
|
175
|
+
endpoint_requirements = options.dig(:route_options, :requirements)
|
176
|
+
requirements.merge!(endpoint_requirements) if endpoint_requirements
|
178
177
|
end
|
179
178
|
end
|
180
179
|
|
@@ -293,7 +292,8 @@ module Grape
|
|
293
292
|
rescue_options: namespace_stackable_with_hash(:rescue_options) || {},
|
294
293
|
rescue_handlers: namespace_reverse_stackable_with_hash(:rescue_handlers) || {},
|
295
294
|
base_only_rescue_handlers: namespace_stackable_with_hash(:base_only_rescue_handlers) || {},
|
296
|
-
all_rescue_handler: namespace_inheritable(:all_rescue_handler)
|
295
|
+
all_rescue_handler: namespace_inheritable(:all_rescue_handler),
|
296
|
+
grape_exceptions_rescue_handler: namespace_inheritable(:grape_exceptions_rescue_handler)
|
297
297
|
|
298
298
|
stack.concat namespace_stackable(:middleware)
|
299
299
|
|
@@ -318,8 +318,8 @@ module Grape
|
|
318
318
|
end
|
319
319
|
|
320
320
|
def build_helpers
|
321
|
-
helpers = namespace_stackable(:helpers)
|
322
|
-
Module.new { helpers
|
321
|
+
helpers = namespace_stackable(:helpers)
|
322
|
+
Module.new { helpers&.each { |mod_to_include| include mod_to_include } }
|
323
323
|
end
|
324
324
|
|
325
325
|
private :build_stack, :build_helpers
|
@@ -345,11 +345,9 @@ module Grape
|
|
345
345
|
end
|
346
346
|
end
|
347
347
|
|
348
|
-
def run_validators(
|
348
|
+
def run_validators(validators, request)
|
349
349
|
validation_errors = []
|
350
350
|
|
351
|
-
validators = validator_factories.map { |options| Grape::Validations::ValidatorFactory.create_validator(**options) }
|
352
|
-
|
353
351
|
ActiveSupport::Notifications.instrument('endpoint_run_validators.grape', endpoint: self, validators: validators, request: request) do
|
354
352
|
validators.each do |validator|
|
355
353
|
validator.validate(request)
|
@@ -367,34 +365,38 @@ module Grape
|
|
367
365
|
|
368
366
|
def run_filters(filters, type = :other)
|
369
367
|
ActiveSupport::Notifications.instrument('endpoint_run_filters.grape', endpoint: self, filters: filters, type: type) do
|
370
|
-
|
368
|
+
filters&.each { |filter| instance_eval(&filter) }
|
371
369
|
end
|
372
370
|
post_extension = DSL::InsideRoute.post_filter_methods(type)
|
373
371
|
extend post_extension if post_extension
|
374
372
|
end
|
375
373
|
|
376
374
|
def befores
|
377
|
-
namespace_stackable(:befores)
|
375
|
+
namespace_stackable(:befores)
|
378
376
|
end
|
379
377
|
|
380
378
|
def before_validations
|
381
|
-
namespace_stackable(:before_validations)
|
379
|
+
namespace_stackable(:before_validations)
|
382
380
|
end
|
383
381
|
|
384
382
|
def after_validations
|
385
|
-
namespace_stackable(:after_validations)
|
383
|
+
namespace_stackable(:after_validations)
|
386
384
|
end
|
387
385
|
|
388
386
|
def afters
|
389
|
-
namespace_stackable(:afters)
|
387
|
+
namespace_stackable(:afters)
|
390
388
|
end
|
391
389
|
|
392
390
|
def finallies
|
393
|
-
namespace_stackable(:finallies)
|
391
|
+
namespace_stackable(:finallies)
|
394
392
|
end
|
395
393
|
|
396
394
|
def validations
|
397
|
-
|
395
|
+
return enum_for(:validations) unless block_given?
|
396
|
+
|
397
|
+
route_setting(:saved_validations)&.each do |saved_validation|
|
398
|
+
yield Grape::Validations::ValidatorFactory.create_validator(**saved_validation)
|
399
|
+
end
|
398
400
|
end
|
399
401
|
|
400
402
|
def options?
|
@@ -27,7 +27,7 @@ module Grape
|
|
27
27
|
|
28
28
|
if presenter
|
29
29
|
embeds = { env: env }
|
30
|
-
embeds[:version] = env[Grape::Env::API_VERSION] if env
|
30
|
+
embeds[:version] = env[Grape::Env::API_VERSION] if env.key?(Grape::Env::API_VERSION)
|
31
31
|
presented_message = presenter.represent(presented_message, embeds).serializable_hash
|
32
32
|
end
|
33
33
|
|
@@ -73,11 +73,11 @@ module Grape
|
|
73
73
|
options = options.dup
|
74
74
|
options[:default] &&= options[:default].to_s
|
75
75
|
message = ::I18n.translate(key, **options)
|
76
|
-
message.
|
76
|
+
message.presence || fallback_message(key, **options)
|
77
77
|
end
|
78
78
|
|
79
79
|
def fallback_message(key, **options)
|
80
|
-
if ::I18n.enforce_available_locales &&
|
80
|
+
if ::I18n.enforce_available_locales && ::I18n.available_locales.exclude?(FALLBACK_LOCALE)
|
81
81
|
key
|
82
82
|
else
|
83
83
|
::I18n.translate(key, locale: FALLBACK_LOCALE, **options)
|
@@ -10,9 +10,4 @@ module Grape
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
-
Grape::Exceptions::MissingGroupTypeError =
|
14
|
-
def initialize(*)
|
15
|
-
super
|
16
|
-
warn '[DEPRECATION] `Grape::Exceptions::MissingGroupTypeError` is deprecated. Use `Grape::Exceptions::MissingGroupType` instead.'
|
17
|
-
end
|
18
|
-
end
|
13
|
+
Grape::Exceptions::MissingGroupTypeError = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('Grape::Exceptions::MissingGroupTypeError', 'Grape::Exceptions::MissingGroupType')
|
@@ -10,9 +10,4 @@ module Grape
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
-
Grape::Exceptions::UnsupportedGroupTypeError =
|
14
|
-
def initialize(*)
|
15
|
-
super
|
16
|
-
warn '[DEPRECATION] `Grape::Exceptions::UnsupportedGroupTypeError` is deprecated. Use `Grape::Exceptions::UnsupportedGroupType` instead.'
|
17
|
-
end
|
18
|
-
end
|
13
|
+
Grape::Exceptions::UnsupportedGroupTypeError = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('Grape::Exceptions::UnsupportedGroupTypeError', 'Grape::Exceptions::UnsupportedGroupType')
|
@@ -13,12 +13,7 @@ module Grape
|
|
13
13
|
attr_reader :errors
|
14
14
|
|
15
15
|
def initialize(errors: [], headers: {}, **_options)
|
16
|
-
@errors =
|
17
|
-
errors.each do |validation_error|
|
18
|
-
@errors[validation_error.params] ||= []
|
19
|
-
@errors[validation_error.params] << validation_error
|
20
|
-
end
|
21
|
-
|
16
|
+
@errors = errors.group_by(&:params)
|
22
17
|
super message: full_messages.join(', '), status: 400, headers: headers
|
23
18
|
end
|
24
19
|
|
@@ -16,9 +16,9 @@ module Grape
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def build_params
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
::ActiveSupport::HashWithIndifferentAccess.new(rack_params).tap do |params|
|
20
|
+
params.deep_merge!(grape_routing_args) if env.key?(Grape::Env::GRAPE_ROUTING_ARGS)
|
21
|
+
end
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
@@ -11,13 +11,10 @@ module Grape
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def build_params
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
def post_process_params(params)
|
20
|
-
Grape::Extensions::DeepSymbolizeHash.deep_symbolize_keys_in(params)
|
14
|
+
rack_params.deep_dup.tap do |params|
|
15
|
+
params.deep_merge!(grape_routing_args) if env.key?(Grape::Env::GRAPE_ROUTING_ARGS)
|
16
|
+
params.deep_symbolize_keys!
|
17
|
+
end
|
21
18
|
end
|
22
19
|
end
|
23
20
|
end
|
@@ -15,9 +15,9 @@ module Grape
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def build_params
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
::Hashie::Mash.new(rack_params).tap do |params|
|
19
|
+
params.deep_merge!(grape_routing_args) if env.key?(Grape::Env::GRAPE_ROUTING_ARGS)
|
20
|
+
end
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
@@ -15,24 +15,24 @@ module Grape
|
|
15
15
|
private
|
16
16
|
|
17
17
|
def serializable?(object)
|
18
|
-
object.respond_to?(:serializable_hash) ||
|
18
|
+
object.respond_to?(:serializable_hash) || array_serializable?(object) || object.is_a?(Hash)
|
19
19
|
end
|
20
20
|
|
21
21
|
def serialize(object)
|
22
22
|
if object.respond_to? :serializable_hash
|
23
23
|
object.serializable_hash
|
24
|
-
elsif
|
24
|
+
elsif array_serializable?(object)
|
25
25
|
object.map(&:serializable_hash)
|
26
26
|
elsif object.is_a?(Hash)
|
27
|
-
|
28
|
-
object.each_pair do |k, v|
|
29
|
-
h[k] = serialize(v)
|
30
|
-
end
|
31
|
-
h
|
27
|
+
object.transform_values { |v| serialize(v) }
|
32
28
|
else
|
33
29
|
object
|
34
30
|
end
|
35
31
|
end
|
32
|
+
|
33
|
+
def array_serializable?(object)
|
34
|
+
object.is_a?(Array) && object.all? { |o| o.respond_to? :serializable_hash }
|
35
|
+
end
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
@@ -28,7 +28,7 @@ module Grape
|
|
28
28
|
|
29
29
|
strategy_info = Grape::Middleware::Auth::Strategies[options[:type]]
|
30
30
|
|
31
|
-
throw(:error, status: 401, message: 'API Authorization Failed.')
|
31
|
+
throw(:error, status: 401, message: 'API Authorization Failed.') if strategy_info.blank?
|
32
32
|
|
33
33
|
strategy = strategy_info.create(@app, options) do |*args|
|
34
34
|
auth_proc_context.instance_exec(*args, &auth_proc)
|
@@ -109,7 +109,7 @@ module Grape
|
|
109
109
|
return :error_response if klass == Grape::Exceptions::InvalidVersionHeader
|
110
110
|
return unless options[:rescue_grape_exceptions] || !options[:rescue_all]
|
111
111
|
|
112
|
-
:error_response
|
112
|
+
options[:grape_exceptions_rescue_handler] || :error_response
|
113
113
|
end
|
114
114
|
|
115
115
|
def rescue_handler_for_any_class(klass)
|
@@ -103,7 +103,7 @@ module Grape
|
|
103
103
|
begin
|
104
104
|
body = (env[Grape::Env::API_REQUEST_BODY] = parser.call(body, env))
|
105
105
|
if body.is_a?(Hash)
|
106
|
-
env[Grape::Env::RACK_REQUEST_FORM_HASH] = if env
|
106
|
+
env[Grape::Env::RACK_REQUEST_FORM_HASH] = if env.key?(Grape::Env::RACK_REQUEST_FORM_HASH)
|
107
107
|
env[Grape::Env::RACK_REQUEST_FORM_HASH].merge(body)
|
108
108
|
else
|
109
109
|
body
|
@@ -57,8 +57,7 @@ module Grape
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def strict_version_vendor_accept_header_presence_check
|
60
|
-
return
|
61
|
-
return if an_accept_header_with_version_and_vendor_is_present?
|
60
|
+
return if versions.blank? || an_accept_header_with_version_and_vendor_is_present?
|
62
61
|
|
63
62
|
fail_with_invalid_accept_header!('API vendor or version not found.')
|
64
63
|
end
|
@@ -101,25 +100,18 @@ module Grape
|
|
101
100
|
end
|
102
101
|
|
103
102
|
def available_media_types
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
]
|
103
|
+
[].tap do |available_media_types|
|
104
|
+
content_types.each_key do |extension|
|
105
|
+
versions.reverse_each do |version|
|
106
|
+
available_media_types << "application/vnd.#{vendor}-#{version}+#{extension}"
|
107
|
+
available_media_types << "application/vnd.#{vendor}-#{version}"
|
108
|
+
end
|
109
|
+
available_media_types << "application/vnd.#{vendor}+#{extension}"
|
112
110
|
end
|
113
|
-
available_media_types << "application/vnd.#{vendor}+#{extension}"
|
114
|
-
end
|
115
|
-
|
116
|
-
available_media_types << "application/vnd.#{vendor}"
|
117
111
|
|
118
|
-
|
119
|
-
available_media_types
|
112
|
+
available_media_types << "application/vnd.#{vendor}"
|
113
|
+
available_media_types.concat(content_types.values.flatten)
|
120
114
|
end
|
121
|
-
|
122
|
-
available_media_types.flatten
|
123
115
|
end
|
124
116
|
|
125
117
|
def headers_contain_wrong_vendor?
|
@@ -130,7 +122,7 @@ module Grape
|
|
130
122
|
|
131
123
|
def headers_contain_wrong_version?
|
132
124
|
header.values.all? do |header_value|
|
133
|
-
version?(header_value) &&
|
125
|
+
version?(header_value) && versions.exclude?(request_version(header_value))
|
134
126
|
end
|
135
127
|
end
|
136
128
|
|
data/lib/grape/router/route.rb
CHANGED
@@ -84,9 +84,7 @@ module Grape
|
|
84
84
|
path, line = *location.scan(SOURCE_LOCATION_REGEXP).first
|
85
85
|
path = File.realpath(path) if Pathname.new(path).relative?
|
86
86
|
expected ||= name
|
87
|
-
warn
|
88
|
-
#{path}:#{line}: The route_xxx methods such as route_#{name} have been deprecated, please use #{expected}.
|
89
|
-
WARNING
|
87
|
+
ActiveSupport::Deprecation.warn("#{path}:#{line}: The route_xxx methods such as route_#{name} have been deprecated, please use #{expected}.")
|
90
88
|
end
|
91
89
|
end
|
92
90
|
end
|
@@ -70,29 +70,21 @@ module Grape
|
|
70
70
|
end
|
71
71
|
|
72
72
|
def evaluate
|
73
|
-
|
74
|
-
@value_hash.each_with_index do |value, index|
|
75
|
-
evaluated[index] = value.evaluate
|
76
|
-
end
|
77
|
-
evaluated
|
73
|
+
@value_hash.map(&:evaluate)
|
78
74
|
end
|
79
75
|
end
|
80
76
|
|
81
77
|
class LazyValueHash < LazyValueEnumerable
|
82
78
|
def initialize(hash)
|
83
79
|
super
|
84
|
-
@value_hash =
|
80
|
+
@value_hash = ActiveSupport::HashWithIndifferentAccess.new
|
85
81
|
hash.each do |key, value|
|
86
82
|
self[key] = value
|
87
83
|
end
|
88
84
|
end
|
89
85
|
|
90
86
|
def evaluate
|
91
|
-
|
92
|
-
@value_hash.each do |key, value|
|
93
|
-
evaluated[key] = value.evaluate
|
94
|
-
end
|
95
|
-
evaluated
|
87
|
+
@value_hash.transform_values(&:evaluate)
|
96
88
|
end
|
97
89
|
end
|
98
90
|
end
|
@@ -66,11 +66,10 @@ module Grape
|
|
66
66
|
end
|
67
67
|
|
68
68
|
define_method :to_hash do
|
69
|
-
merge_hash = {}
|
70
|
-
setting_name.each_key { |k| merge_hash[k] = send("#{k}_context").to_hash }
|
71
|
-
|
72
69
|
@settings.to_hash.merge(
|
73
|
-
merge_hash
|
70
|
+
setting_name.each_key.with_object({}) do |k, merge_hash|
|
71
|
+
merge_hash[k] = send("#{k}_context").to_hash
|
72
|
+
end
|
74
73
|
)
|
75
74
|
end
|
76
75
|
end
|