grape 1.7.0 → 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 +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
|