grape 1.7.0 → 1.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +46 -0
- data/CONTRIBUTING.md +31 -1
- data/README.md +38 -8
- 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 +3 -2
- data/lib/grape/dsl/inside_route.rb +6 -6
- data/lib/grape/dsl/parameters.rb +6 -1
- data/lib/grape/dsl/request_response.rb +3 -2
- data/lib/grape/dsl/settings.rb +2 -6
- data/lib/grape/endpoint.rb +21 -19
- data/lib/grape/error_formatter/base.rb +1 -1
- data/lib/grape/exceptions/base.rb +4 -3
- 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/stack.rb +1 -1
- data/lib/grape/middleware/versioner/header.rb +11 -19
- data/lib/grape/request.rb +1 -1
- data/lib/grape/router/attribute_translator.rb +1 -1
- data/lib/grape/router/route.rb +1 -3
- data/lib/grape/types/invalid_value.rb +8 -0
- data/lib/grape/util/cache.rb +1 -1
- 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 +9 -3
- 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/types/invalid_value.rb +0 -7
- 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 +19 -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 +15 -21
- data/spec/grape/dsl/desc_spec.rb +84 -85
- 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 +11 -10
- data/spec/grape/exceptions/body_parse_errors_spec.rb +40 -0
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +3 -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/integration/rack_spec.rb +6 -5
- data/spec/grape/middleware/base_spec.rb +7 -5
- data/spec/grape/middleware/formatter_spec.rb +7 -7
- 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 +56 -0
- data/spec/grape/validations_spec.rb +36 -12
- data/spec/shared/deprecated_class_examples.rb +16 -0
- metadata +112 -114
- 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
- data/spec/grape/dsl/configuration_spec.rb +0 -14
- data/spec/grape/validations/attributes_iterator_spec.rb +0 -4
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,3 +1,49 @@
|
|
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)
|
23
|
+
|
24
|
+
#### Features
|
25
|
+
|
26
|
+
* [#2288](https://github.com/ruby-grape/grape/pull/2288): Droped support for Ruby 2.5 - [@ericproulx](https://github.com/ericproulx).
|
27
|
+
* [#2288](https://github.com/ruby-grape/grape/pull/2288): Updated rubocop to 1.41.0 - [@ericproulx](https://github.com/ericproulx).
|
28
|
+
* [#2296](https://github.com/ruby-grape/grape/pull/2296): Fix cops and enables some - [@ericproulx](https://github.com/ericproulx).
|
29
|
+
* [#2302](https://github.com/ruby-grape/grape/pull/2302): Rack < 3 and update rack-test - [@ericproulx](https://github.com/ericproulx).
|
30
|
+
* [#2303](https://github.com/ruby-grape/grape/pull/2302): Rack >= 1.3.0 - [@ericproulx](https://github.com/ericproulx).
|
31
|
+
* [#2301](https://github.com/ruby-grape/grape/pull/2301): Revisit GH workflows - [@ericproulx](https://github.com/ericproulx).
|
32
|
+
* [#2311](https://github.com/ruby-grape/grape/pull/2311): Fix tests by pinning rack-test to < 2.1 - [@duffn](https://github.com/duffn).
|
33
|
+
* [#2310](https://github.com/ruby-grape/grape/pull/2310): Fix YARD docs markdown rendering - [@duffn](https://github.com/duffn).
|
34
|
+
* [#2317](https://github.com/ruby-grape/grape/pull/2317): Remove maruku and rubocop-ast as direct development/testing dependencies - [@ericproulx](https://github.com/ericproulx).
|
35
|
+
* [#2292](https://github.com/ruby-grape/grape/pull/2292): Introduce Docker to local development - [@ericproulx](https://github.com/ericproulx).
|
36
|
+
* [#2325](https://github.com/ruby-grape/grape/pull/2325): Change edge test workflows only run on demand - [@dblock](https://github.com/dblock).
|
37
|
+
* [#2324](https://github.com/ruby-grape/grape/pull/2324): Expose default in the description dsl - [@dhruvCW](https://github.com/dhruvCW).
|
38
|
+
|
39
|
+
#### Fixes
|
40
|
+
|
41
|
+
* [#2299](https://github.com/ruby-grape/grape/pull/2299): Fix, do not use kwargs for empty args - [@dm1try](https://github.com/dm1try).
|
42
|
+
* [#2307](https://github.com/ruby-grape/grape/pull/2307): Fixed autoloading of InvalidValue - [@fixlr](https://github.com/fixlr).
|
43
|
+
* [#2315](https://github.com/ruby-grape/grape/pull/2315): Update rspec - [@ericproulx](https://github.com/ericproulx).
|
44
|
+
* [#2319](https://github.com/ruby-grape/grape/pull/2319): Update rubocop - [@ericproulx](https://github.com/ericproulx).
|
45
|
+
* [#2323](https://github.com/ruby-grape/grape/pull/2323): Fix using endless ranges for values parameter - [@dhruvCW](https://github.com/dhruvCW).
|
46
|
+
|
1
47
|
### 1.7.0 (2022/12/20)
|
2
48
|
|
3
49
|
#### Features
|
data/CONTRIBUTING.md
CHANGED
@@ -23,6 +23,34 @@ git pull upstream master
|
|
23
23
|
git checkout -b my-feature-branch
|
24
24
|
```
|
25
25
|
|
26
|
+
### Docker
|
27
|
+
|
28
|
+
If you're familiar with [Docker](https://www.docker.com/), you can run everything through the following command:
|
29
|
+
|
30
|
+
```
|
31
|
+
docker-compose run --rm --build grape <command_and_parameters>
|
32
|
+
```
|
33
|
+
|
34
|
+
About the execution process:
|
35
|
+
- displays Ruby, Rubygems, Bundle and Gemfile version when starting:
|
36
|
+
```
|
37
|
+
ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x86_64-linux-musl]
|
38
|
+
rubygems 3.4.12
|
39
|
+
Bundler version 2.4.1 (2022-12-24 commit f3175f033c)
|
40
|
+
Running default Gemfile
|
41
|
+
```
|
42
|
+
- keeps the gems to the latest possible version
|
43
|
+
- executes under `bundle exec`
|
44
|
+
|
45
|
+
Here are some examples:
|
46
|
+
|
47
|
+
- running all specs `docker-compose run --rm --build grape rspec`
|
48
|
+
- running rspec on a specific file `docker-compose run --rm --build grape rspec spec/:file_path`
|
49
|
+
- running task `docker-compose run --rm --build grape rake <task_name>`
|
50
|
+
- running rubocop `docker-compose run --rm --build grape rubocop`
|
51
|
+
- running all specs on a specific ruby version (e.g 2.7.7) `RUBY_VERSION=2.7.7 docker-compose run --rm --build grape rspec`
|
52
|
+
- running specs on a specific gemfile (e.g rails_7_0.gemfile) `docker-compose run -e GEMFILE=rails_7_0 --rm --build grape rspec`
|
53
|
+
|
26
54
|
#### Bundle Install and Test
|
27
55
|
|
28
56
|
Ensure that you can build the project and run tests.
|
@@ -58,6 +86,8 @@ Make sure that `bundle exec rake` completes without errors.
|
|
58
86
|
|
59
87
|
Document any external behavior in the [README](README.md).
|
60
88
|
|
89
|
+
You should also document code as necessary, using current code as examples. This project uses [YARD](https://yardoc.org/). You can run and preview the docs locally by [installing `yard`](https://yardoc.org/), running `yard server --reload` and view the docs at http://localhost:8808.
|
90
|
+
|
61
91
|
#### Update Changelog
|
62
92
|
|
63
93
|
Add a line to [CHANGELOG](CHANGELOG.md) under *Next Release*. Make it look like every other line, including your name and link to your Github account.
|
@@ -115,7 +145,7 @@ git push origin my-feature-branch -f
|
|
115
145
|
|
116
146
|
#### Check on Your Pull Request
|
117
147
|
|
118
|
-
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.
|
119
149
|
|
120
150
|
#### Be Patient
|
121
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,26 +524,26 @@ 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
|
|
539
539
|
class V1 < Grape::API
|
540
540
|
version 'v1'
|
541
|
-
mount BasicAPI, with: { entity: mounted { configuration[:entity] || API::
|
541
|
+
mount BasicAPI, with: { entity: mounted { configuration[:entity] || API::Entities::Status } }
|
542
542
|
end
|
543
543
|
|
544
544
|
class V2 < Grape::API
|
545
545
|
version 'v2'
|
546
|
-
mount BasicAPI, with: { entity: mounted { configuration[:entity] || API::
|
546
|
+
mount BasicAPI, with: { entity: mounted { configuration[:entity] || API::Entities::V2::Status } }
|
547
547
|
end
|
548
548
|
```
|
549
549
|
|
@@ -638,6 +638,7 @@ desc 'Returns your public timeline.' do
|
|
638
638
|
params API::Entities::Status.documentation
|
639
639
|
success API::Entities::Entity
|
640
640
|
failure [[401, 'Unauthorized', 'Entities::Error']]
|
641
|
+
default { code: 500, message: 'InvalidRequest', model: Entities::Error }
|
641
642
|
named 'My named route'
|
642
643
|
headers XAuthToken: {
|
643
644
|
description: 'Validates your identity',
|
@@ -662,8 +663,9 @@ end
|
|
662
663
|
|
663
664
|
* `detail`: A more enhanced description
|
664
665
|
* `params`: Define parameters directly from an `Entity`
|
665
|
-
* `success`: (former entity) The `Entity` to be used to present
|
666
|
-
* `failure`: (former http_codes) A definition of the used failure HTTP Codes and Entities
|
666
|
+
* `success`: (former entity) The `Entity` to be used to present the success response for this route.
|
667
|
+
* `failure`: (former http_codes) A definition of the used failure HTTP Codes and Entities.
|
668
|
+
* `default`: The definition and `Entity` used to present the default response for this route.
|
667
669
|
* `named`: A helper to give a route a name and find it with this name in the documentation Hash
|
668
670
|
* `headers`: A definition of the used Headers
|
669
671
|
* Other options can be found in [grape-swagger][grape-swagger]
|
@@ -1586,6 +1588,15 @@ params do
|
|
1586
1588
|
end
|
1587
1589
|
```
|
1588
1590
|
|
1591
|
+
Note endless ranges are also supported with ActiveSupport >= 6.0, but they require that the type be provided.
|
1592
|
+
|
1593
|
+
```ruby
|
1594
|
+
params do
|
1595
|
+
requires :minimum, type: Integer, values: 10..
|
1596
|
+
optional :maximum, type: Integer, values: ..10
|
1597
|
+
end
|
1598
|
+
```
|
1599
|
+
|
1589
1600
|
Note that *both* range endpoints have to be a `#kind_of?` your `:type` option (if you don't supply the `:type` option, it will be guessed to be equal to the class of the range's first endpoint). So the following is invalid:
|
1590
1601
|
|
1591
1602
|
```ruby
|
@@ -2613,6 +2624,14 @@ class Twitter::API < Grape::API
|
|
2613
2624
|
end
|
2614
2625
|
```
|
2615
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
|
+
|
2616
2635
|
You can also rescue specific exceptions.
|
2617
2636
|
|
2618
2637
|
```ruby
|
@@ -3340,6 +3359,17 @@ end
|
|
3340
3359
|
|
3341
3360
|
Use `body false` to return `204 No Content` without any data or content-type.
|
3342
3361
|
|
3362
|
+
If you want to empty the body with an HTTP status code other than `204 No Content`, you can override the status code after specifying `body false` as follows
|
3363
|
+
|
3364
|
+
```ruby
|
3365
|
+
class API < Grape::API
|
3366
|
+
get '/' do
|
3367
|
+
body false
|
3368
|
+
status 304
|
3369
|
+
end
|
3370
|
+
end
|
3371
|
+
```
|
3372
|
+
|
3343
3373
|
You can also set the response to a file with `sendfile`. This works with the
|
3344
3374
|
[Rack::Sendfile](https://www.rubydoc.info/gems/rack/Rack/Sendfile) middleware to optimally send
|
3345
3375
|
the file through your web server software.
|
data/grape.gemspec
CHANGED
@@ -20,7 +20,7 @@ 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'
|
@@ -32,5 +32,5 @@ Gem::Specification.new do |s|
|
|
32
32
|
s.files += Dir['lib/**/*']
|
33
33
|
s.test_files = Dir['spec/**/*']
|
34
34
|
s.require_paths = ['lib']
|
35
|
-
s.required_ruby_version = '>= 2.
|
35
|
+
s.required_ruby_version = '>= 2.6.0'
|
36
36
|
end
|
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)
|
@@ -98,7 +98,8 @@ module Grape
|
|
98
98
|
:produces,
|
99
99
|
:consumes,
|
100
100
|
:security,
|
101
|
-
:tags
|
101
|
+
:tags,
|
102
|
+
:default
|
102
103
|
)
|
103
104
|
config_context.define_singleton_method(:configuration) do
|
104
105
|
endpoint_configuration
|
@@ -95,7 +95,7 @@ module Grape
|
|
95
95
|
return yield if has_passed_children
|
96
96
|
|
97
97
|
key = params_nested_path[0]
|
98
|
-
key += "[#{params_nested_path[1
|
98
|
+
key += "[#{params_nested_path[1..].join('][')}]" if params_nested_path.size > 1
|
99
99
|
|
100
100
|
route_options_params = options[:route_options][:params] || {}
|
101
101
|
type = route_options_params.dig(key, :type)
|
@@ -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
|
data/lib/grape/dsl/parameters.rb
CHANGED
@@ -62,7 +62,12 @@ module Grape
|
|
62
62
|
params_block = named_params.fetch(name) do
|
63
63
|
raise "Params :#{name} not found!"
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
|
+
if options.empty?
|
67
|
+
instance_exec(options, ¶ms_block)
|
68
|
+
else
|
69
|
+
instance_exec(**options, ¶ms_block)
|
70
|
+
end
|
66
71
|
end
|
67
72
|
end
|
68
73
|
alias use_scope use
|
@@ -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]
|
@@ -125,7 +126,7 @@ module Grape
|
|
125
126
|
:base_only_rescue_handlers
|
126
127
|
end
|
127
128
|
|
128
|
-
namespace_reverse_stackable
|
129
|
+
namespace_reverse_stackable(handler_type, args.to_h { |arg| [arg, handler] })
|
129
130
|
end
|
130
131
|
|
131
132
|
namespace_stackable(:rescue_options, options)
|
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,13 +292,14 @@ 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
|
|
300
300
|
if namespace_inheritable(:version)
|
301
301
|
stack.use Grape::Middleware::Versioner.using(namespace_inheritable(:version_options)[:using]),
|
302
|
-
versions: namespace_inheritable(:version)
|
302
|
+
versions: namespace_inheritable(:version)&.flatten,
|
303
303
|
version_options: namespace_inheritable(:version_options),
|
304
304
|
prefix: namespace_inheritable(:root_prefix),
|
305
305
|
mount_path: namespace_stackable(:mount_path).first
|
@@ -318,14 +318,14 @@ 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
|
326
326
|
|
327
327
|
def execute
|
328
|
-
@block
|
328
|
+
@block&.call(self)
|
329
329
|
end
|
330
330
|
|
331
331
|
def 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
|
|
@@ -10,9 +10,10 @@ module Grape
|
|
10
10
|
attr_reader :status, :headers
|
11
11
|
|
12
12
|
def initialize(status: nil, message: nil, headers: nil, **_options)
|
13
|
+
super(message)
|
14
|
+
|
13
15
|
@status = status
|
14
16
|
@headers = headers
|
15
|
-
super(message)
|
16
17
|
end
|
17
18
|
|
18
19
|
def [](index)
|
@@ -72,11 +73,11 @@ module Grape
|
|
72
73
|
options = options.dup
|
73
74
|
options[:default] &&= options[:default].to_s
|
74
75
|
message = ::I18n.translate(key, **options)
|
75
|
-
message.
|
76
|
+
message.presence || fallback_message(key, **options)
|
76
77
|
end
|
77
78
|
|
78
79
|
def fallback_message(key, **options)
|
79
|
-
if ::I18n.enforce_available_locales &&
|
80
|
+
if ::I18n.enforce_available_locales && ::I18n.available_locales.exclude?(FALLBACK_LOCALE)
|
80
81
|
key
|
81
82
|
else
|
82
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
|