grape 2.3.0 → 3.0.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.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +69 -0
  3. data/CONTRIBUTING.md +2 -10
  4. data/README.md +106 -43
  5. data/UPGRADING.md +90 -1
  6. data/grape.gemspec +4 -4
  7. data/lib/grape/api/instance.rb +51 -73
  8. data/lib/grape/api.rb +56 -89
  9. data/lib/grape/cookies.rb +31 -25
  10. data/lib/grape/dry_types.rb +48 -4
  11. data/lib/grape/dsl/callbacks.rb +8 -58
  12. data/lib/grape/dsl/desc.rb +8 -67
  13. data/lib/grape/dsl/headers.rb +1 -1
  14. data/lib/grape/dsl/helpers.rb +60 -65
  15. data/lib/grape/dsl/inside_route.rb +26 -61
  16. data/lib/grape/dsl/logger.rb +3 -6
  17. data/lib/grape/dsl/middleware.rb +22 -40
  18. data/lib/grape/dsl/parameters.rb +10 -19
  19. data/lib/grape/dsl/request_response.rb +136 -139
  20. data/lib/grape/dsl/routing.rb +230 -194
  21. data/lib/grape/dsl/settings.rb +22 -134
  22. data/lib/grape/dsl/validations.rb +37 -45
  23. data/lib/grape/endpoint.rb +91 -126
  24. data/lib/grape/error_formatter/base.rb +2 -0
  25. data/lib/grape/exceptions/base.rb +1 -1
  26. data/lib/grape/exceptions/conflicting_types.rb +11 -0
  27. data/lib/grape/exceptions/invalid_parameters.rb +11 -0
  28. data/lib/grape/exceptions/missing_group_type.rb +0 -2
  29. data/lib/grape/exceptions/too_deep_parameters.rb +11 -0
  30. data/lib/grape/exceptions/unknown_auth_strategy.rb +11 -0
  31. data/lib/grape/exceptions/unknown_params_builder.rb +11 -0
  32. data/lib/grape/exceptions/unsupported_group_type.rb +0 -2
  33. data/lib/grape/extensions/active_support/hash_with_indifferent_access.rb +2 -5
  34. data/lib/grape/extensions/hash.rb +2 -1
  35. data/lib/grape/extensions/hashie/mash.rb +3 -5
  36. data/lib/grape/locale/en.yml +44 -44
  37. data/lib/grape/middleware/auth/base.rb +11 -32
  38. data/lib/grape/middleware/auth/dsl.rb +22 -29
  39. data/lib/grape/middleware/base.rb +30 -11
  40. data/lib/grape/middleware/error.rb +14 -32
  41. data/lib/grape/middleware/formatter.rb +40 -72
  42. data/lib/grape/middleware/stack.rb +28 -38
  43. data/lib/grape/middleware/versioner/accept_version_header.rb +2 -4
  44. data/lib/grape/middleware/versioner/base.rb +30 -56
  45. data/lib/grape/middleware/versioner/header.rb +2 -2
  46. data/lib/grape/middleware/versioner/param.rb +2 -3
  47. data/lib/grape/middleware/versioner/path.rb +1 -1
  48. data/lib/grape/namespace.rb +11 -0
  49. data/lib/grape/params_builder/base.rb +20 -0
  50. data/lib/grape/params_builder/hash.rb +11 -0
  51. data/lib/grape/params_builder/hash_with_indifferent_access.rb +11 -0
  52. data/lib/grape/params_builder/hashie_mash.rb +11 -0
  53. data/lib/grape/params_builder.rb +32 -0
  54. data/lib/grape/request.rb +161 -22
  55. data/lib/grape/router/route.rb +1 -1
  56. data/lib/grape/router.rb +27 -8
  57. data/lib/grape/util/api_description.rb +56 -0
  58. data/lib/grape/util/base_inheritable.rb +5 -2
  59. data/lib/grape/util/inheritable_setting.rb +7 -0
  60. data/lib/grape/util/media_type.rb +1 -1
  61. data/lib/grape/util/registry.rb +1 -1
  62. data/lib/grape/validations/contract_scope.rb +2 -2
  63. data/lib/grape/validations/params_documentation.rb +50 -0
  64. data/lib/grape/validations/params_scope.rb +46 -56
  65. data/lib/grape/validations/types/array_coercer.rb +2 -3
  66. data/lib/grape/validations/types/dry_type_coercer.rb +4 -11
  67. data/lib/grape/validations/types/primitive_coercer.rb +1 -28
  68. data/lib/grape/validations/types.rb +10 -25
  69. data/lib/grape/validations/validators/base.rb +2 -9
  70. data/lib/grape/validations/validators/except_values_validator.rb +1 -1
  71. data/lib/grape/validations/validators/presence_validator.rb +1 -1
  72. data/lib/grape/validations/validators/regexp_validator.rb +1 -1
  73. data/lib/grape/version.rb +1 -1
  74. data/lib/grape.rb +18 -9
  75. metadata +35 -20
  76. data/lib/grape/api/helpers.rb +0 -9
  77. data/lib/grape/dsl/api.rb +0 -19
  78. data/lib/grape/dsl/configuration.rb +0 -15
  79. data/lib/grape/error_formatter/jsonapi.rb +0 -7
  80. data/lib/grape/http/headers.rb +0 -56
  81. data/lib/grape/middleware/helpers.rb +0 -12
  82. data/lib/grape/parser/jsonapi.rb +0 -7
  83. data/lib/grape/types/invalid_value.rb +0 -8
  84. data/lib/grape/util/lazy/object.rb +0 -45
  85. data/lib/grape/util/strict_hash_configuration.rb +0 -108
  86. data/lib/grape/validations/attributes_doc.rb +0 -60
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eefbc6eed618a448bcc9657c03ca73f5771f22b5f13b4c56cacb7ec7e05750ac
4
- data.tar.gz: 6506e73d4ce49cdf54c142acee7085217bd6f55211f86b74a50d23a83ae48c02
3
+ metadata.gz: 919d93a2a8cd39c07b1a043fb342cbecdf5ce4a85b7696188d2de629f92b02a1
4
+ data.tar.gz: c33240607db8c00cba0fc1d5cf5d9c50809c561d3c29b10f246fe9e96423d277
5
5
  SHA512:
6
- metadata.gz: 6e5dab9502a1484f267e9881b8a368cfe809f47eaf9870d14db2002c63c48863f92bbd561c54dd81b0c4e4ff416a7fa7abc121c0052576dc0d7cb088d425d282
7
- data.tar.gz: e78c3fc83ae2a908ef510a387cd31060a13eeb23d7d209c842f2d7e64286ca21e506472fd7ca9f397e1169f7e74fc439a097c376d4ba6682b1c091009fc52acd
6
+ metadata.gz: baf576a03f0a56114032b12d842964d8fb5587de44bdded21c2faecca9a2da3bf7f8eb36aa7a8cec4b4b9b4904ab92ab9763045688452e88f891fc7bf781e527
7
+ data.tar.gz: 48dcc1cab168fd88fd7b839da6c0bbaecc8108c6eac62cc9e1f0f2c09c3e9fd5db2756fa246fce2fb2822c92eff5dc8ef6e2b694edf9b08e244b7c0749fb6633
data/CHANGELOG.md CHANGED
@@ -1,3 +1,71 @@
1
+ ### 3.0.0 (2025-11-15)
2
+
3
+ #### Features
4
+
5
+ * [#2572](https://github.com/ruby-grape/grape/pull/2572): Drop support ruby 2.7 and active_support 6.1 - [@ericproulx](https://github.com/ericproulx).
6
+ * [#2573](https://github.com/ruby-grape/grape/pull/2573): Clean up deprecated code - [@ericproulx](https://github.com/ericproulx).
7
+ * [#2575](https://github.com/ruby-grape/grape/pull/2575): Refactor Api description class - [@ericproulx](https://github.com/ericproulx).
8
+ * [#2577](https://github.com/ruby-grape/grape/pull/2577): Deprecate `return` in endpoint execution - [@ericproulx](https://github.com/ericproulx).
9
+ * [#2580](https://github.com/ruby-grape/grape/pull/2580): Refactor endpoint helpers and error middleware integration - [@ericproulx](https://github.com/ericproulx).
10
+ * [#2581](https://github.com/ruby-grape/grape/pull/2581): Delegate `to_s` in Grape::API::Instance - [@ericproulx](https://github.com/ericproulx).
11
+ * [#2582](https://github.com/ruby-grape/grape/pull/2582): Fix leaky slash when normalizing - [@ericproulx](https://github.com/ericproulx).
12
+ * [#2583](https://github.com/ruby-grape/grape/pull/2583): Optimize api parameter documentation and memory usage - [@ericproulx](https://github.com/ericproulx).
13
+ * [#2589](https://github.com/ruby-grape/grape/pull/2589): Replace `send` by `__send__` in codebase - [@ericproulx](https://github.com/ericproulx).
14
+ * [#2598](https://github.com/ruby-grape/grape/pull/2598): Refactor settings DSL to use explicit methods instead of dynamic generation - [@ericproulx](https://github.com/ericproulx).
15
+ * [#2599](https://github.com/ruby-grape/grape/pull/2599): Simplify settings DSL get_or_set method and optimize logger implementation - [@ericproulx](https://github.com/ericproulx).
16
+ * [#2600](https://github.com/ruby-grape/grape/pull/2600): Refactor versioner middleware: simplify base class and improve consistency - [@ericproulx](https://github.com/ericproulx).
17
+ * [#2601](https://github.com/ruby-grape/grape/pull/2601): Refactor route_setting internal usage to use inheritable_setting.route for improved consistency and performance - [@ericproulx](https://github.com/ericproulx).
18
+ * [#2602](https://github.com/ruby-grape/grape/pull/2602): Remove `namespace_reverse_stackable` from public DSL interface and use direct inheritable_setting access - [@ericproulx](https://github.com/ericproulx).
19
+ * [#2603](https://github.com/ruby-grape/grape/pull/2603): Remove `namespace_stackable_with_hash` from public interface and move to internal InheritableSetting - [@ericproulx](https://github.com/ericproulx).
20
+ * [#2604](https://github.com/ruby-grape/grape/pull/2604): Enable branch coverage - [@ericproulx](https://github.com/ericproulx).
21
+ * [#2605](https://github.com/ruby-grape/grape/pull/2605): Add Rack 3.2 support with new gemfile and CI integration - [@ericproulx](https://github.com/ericproulx).
22
+ * [#2607](https://github.com/ruby-grape/grape/pull/2607): Remove namespace_stackable and namespace_inheritable from public API - [@ericproulx](https://github.com/ericproulx).
23
+ * [#2615](https://github.com/ruby-grape/grape/pull/2615): Remove manual toc and tod danger check - [@alexanderadam](https://github.com/alexanderadam).
24
+ * [#2612](https://github.com/ruby-grape/grape/pull/2612): Avoid multiple mount pollution - [@alexanderadam](https://github.com/alexanderadam).
25
+ * [#2617](https://github.com/ruby-grape/grape/pull/2617): Migrate from `ActiveSupport::Configurable` to `Dry::Configurable` - [@ericproulx](https://github.com/ericproulx).
26
+ * [#2618](https://github.com/ruby-grape/grape/pull/2618): Modernize argument delegation for Ruby 3+ compatibility - [@ericproulx](https://github.com/ericproulx).
27
+ * [#2623](https://github.com/ruby-grape/grape/pull/2623): Refactor coercer caching to use `Grape::Util::Cache` - [@ericproulx](https://github.com/ericproulx).
28
+
29
+ #### Fixes
30
+
31
+ * [#2586](https://github.com/ruby-grape/grape/pull/2586): Limit helpers DSL public scope - [@ericproulx](https://github.com/ericproulx).
32
+ * [#2588](https://github.com/ruby-grape/grape/pull/2588): Fix defaut format regression on */* - [@ericproulx](https://github.com/ericproulx).
33
+ * [#2593](https://github.com/ruby-grape/grape/pull/2593): Fix warning message when overriding global registry key - [@ericproulx](https://github.com/ericproulx).
34
+ * [#2594](https://github.com/ruby-grape/grape/pull/2594): Fix routes memoization - [@ericproulx](https://github.com/ericproulx).
35
+ * [#2595](https://github.com/ruby-grape/grape/pull/2595): Keep `within_namespace` as part of our internal api - [@ericproulx](https://github.com/ericproulx).
36
+ * [#2596](https://github.com/ruby-grape/grape/pull/2596): Remove `namespace_reverse_stackable_with_hash` from public scope - [@ericproulx](https://github.com/ericproulx).
37
+ * [#2621](https://github.com/ruby-grape/grape/pull/2621): Update upgrading notes regarding `return` usage and simplify endpoint execution - [@ericproulx](https://github.com/ericproulx).
38
+ * [#2622](https://github.com/ruby-grape/grape/pull/2622): Use `require_relative` instead of `$LOAD_PATH` in gemspec - [@ericproulx](https://github.com/ericproulx).
39
+
40
+ ### 2.4.0 (2025-06-18)
41
+
42
+ #### Features
43
+
44
+ * [#2532](https://github.com/ruby-grape/grape/pull/2532): Update RuboCop 1.71.2 - [@ericproulx](https://github.com/ericproulx).
45
+ * [#2535](https://github.com/ruby-grape/grape/pull/2535): Delegate calls to inner objects - [@ericproulx](https://github.com/ericproulx).
46
+ * [#2537](https://github.com/ruby-grape/grape/pull/2537): Use activesupport `try` pattern - [@ericproulx](https://github.com/ericproulx).
47
+ * [#2536](https://github.com/ruby-grape/grape/pull/2536): Update normalize_path like Rails - [@ericproulx](https://github.com/ericproulx).
48
+ * [#2540](https://github.com/ruby-grape/grape/pull/2540): Introduce params builder with symbolized short name - [@ericproulx](https://github.com/ericproulx).
49
+ * [#2550](https://github.com/ruby-grape/grape/pull/2550): Drop ActiveSupport 6.0 - [@ericproulx](https://github.com/ericproulx).
50
+ * [#2549](https://github.com/ruby-grape/grape/pull/2549): Delegate cookies management to `Grape::Request` - [@ericproulx](https://github.com/ericproulx).
51
+ * [#2554](https://github.com/ruby-grape/grape/pull/2554): Remove `Grape::Http::Headers` and `Grape::Util::Lazy::Object` - [@ericproulx](https://github.com/ericproulx).
52
+ * [#2556](https://github.com/ruby-grape/grape/pull/2556): Remove unused `Grape::Request::DEFAULT_PARAMS_BUILDER` constant - [@eriklovmo](https://github.com/eriklovmo).
53
+ * [#2558](https://github.com/ruby-grape/grape/pull/2558): Add Ruby's option `enable_frozen_string_literal` in CI - [@ericproulx](https://github.com/ericproulx).
54
+ * [#2557](https://github.com/ruby-grape/grape/pull/2557): Add `lint!` - [@ericproulx](https://github.com/ericproulx).
55
+ * [#2561](https://github.com/ruby-grape/grape/pull/2561): Optimize hash alloc for middleware's default options - [@ericproulx](https://github.com/ericproulx).
56
+ * [#2563](https://github.com/ruby-grape/grape/pull/2563): Update `Grape::Middleware::Auth::Base` - [@ericproulx](https://github.com/ericproulx).
57
+ * [#2571](https://github.com/ruby-grape/grape/pull/2571): Update RuboCop 1.75.8 - [@pieterocp](https://github.com/pieterocp).
58
+
59
+ #### Fixes
60
+
61
+ * [#2538](https://github.com/ruby-grape/grape/pull/2538): Fix validating nested json array params - [@mohammednasser-32](https://github.com/mohammednasser-32).
62
+ * [#2543](https://github.com/ruby-grape/grape/pull/2543): Fix array allocation on mount - [@ericproulx](https://github.com/ericproulx).
63
+ * [#2546](https://github.com/ruby-grape/grape/pull/2546): Fix middleware with keywords - [@ericproulx](https://github.com/ericproulx).
64
+ * [#2547](https://github.com/ruby-grape/grape/pull/2547): Remove jsonapi related code - [@ericproulx](https://github.com/ericproulx).
65
+ * [#2548](https://github.com/ruby-grape/grape/pull/2548): Formatting from header acts like versioning from header - [@ericproulx](https://github.com/ericproulx).
66
+ * [#2552](https://github.com/ruby-grape/grape/pull/2552): Fix declared params optional array - [@ericproulx](https://github.com/ericproulx).
67
+ * [#2553](https://github.com/ruby-grape/grape/pull/2553): Improve performance of query params parsing - [@ericproulx](https://github.com/ericproulx).
68
+
1
69
  ### 2.3.0 (2025-02-08)
2
70
 
3
71
  #### Features
@@ -1136,3 +1204,4 @@
1136
1204
  ### 0.1.0 (2010/11/13)
1137
1205
 
1138
1206
  * Initial public release - [@mbleigh](https://github.com/mbleigh).
1207
+
data/CONTRIBUTING.md CHANGED
@@ -1,7 +1,7 @@
1
1
  Contributing to Grape
2
2
  =====================
3
3
 
4
- Grape is work of [hundreds of contributors](https://github.com/ruby-grape/grape/graphs/contributors). You're encouraged to submit [pull requests](https://github.com/ruby-grape/grape/pulls), [propose features and discuss issues](https://github.com/ruby-grape/grape/issues). When in doubt, ask a question in the [Grape Google Group](http://groups.google.com/group/ruby-grape).
4
+ Grape is work of [hundreds of contributors](https://github.com/ruby-grape/grape/graphs/contributors). You're encouraged to submit [pull requests](https://github.com/ruby-grape/grape/pulls), [propose features and discuss issues](https://github.com/ruby-grape/grape/issues).
5
5
 
6
6
  #### Fork the Project
7
7
 
@@ -48,7 +48,7 @@ Here are some examples:
48
48
  - running rspec on a specific file `docker-compose run --rm --build grape rspec spec/:file_path`
49
49
  - running task `docker-compose run --rm --build grape rake <task_name>`
50
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`
51
+ - running all specs on a specific ruby version (e.g 3.0) `RUBY_VERSION=3.0 docker-compose run --rm --build grape rspec`
52
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
53
 
54
54
  #### Bundle Install and Test
@@ -60,14 +60,6 @@ bundle install
60
60
  bundle exec rake
61
61
  ```
62
62
 
63
- Run tests against all supported versions of Rails.
64
-
65
- ```
66
- gem install appraisal
67
- appraisal install
68
- appraisal rake spec
69
- ```
70
-
71
63
  #### Write Tests
72
64
 
73
65
  Try to write a test that reproduces the problem you're trying to fix or describes a feature that you want to build. Add to [spec/grape](spec/grape).
data/README.md CHANGED
@@ -1,11 +1,8 @@
1
1
  ![grape logo](grape.png)
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/grape.svg)](http://badge.fury.io/rb/grape)
4
- [![Build Status](https://github.com/ruby-grape/grape/workflows/test/badge.svg?branch=master)](https://github.com/ruby-grape/grape/actions)
5
- [![Code Climate](https://codeclimate.com/github/ruby-grape/grape.svg)](https://codeclimate.com/github/ruby-grape/grape)
4
+ [![test](https://github.com/ruby-grape/grape/actions/workflows/test.yml/badge.svg)](https://github.com/ruby-grape/grape/actions/workflows/test.yml)
6
5
  [![Coverage Status](https://coveralls.io/repos/github/ruby-grape/grape/badge.svg?branch=master)](https://coveralls.io/github/ruby-grape/grape?branch=master)
7
- [![Inline docs](https://inch-ci.org/github/ruby-grape/grape.svg)](https://inch-ci.org/github/ruby-grape/grape)
8
- [![Join the chat at https://gitter.im/ruby-grape/grape](https://badges.gitter.im/ruby-grape/grape.svg)](https://gitter.im/ruby-grape/grape?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
9
6
 
10
7
  ## Table of Contents
11
8
 
@@ -31,6 +28,8 @@
31
28
  - [Header](#header)
32
29
  - [Accept-Version Header](#accept-version-header)
33
30
  - [Param](#param)
31
+ - [Linting](#linting)
32
+ - [Bug in Rack::ETag under Rack 3.X](#bug-in-racketag-under-rack-3x)
34
33
  - [Describing Methods](#describing-methods)
35
34
  - [Configuration](#configuration)
36
35
  - [Parameters](#parameters)
@@ -138,13 +137,17 @@
138
137
  - [Reloading API Changes in Development](#reloading-api-changes-in-development)
139
138
  - [Reloading in Rack Applications](#reloading-in-rack-applications)
140
139
  - [Reloading in Rails Applications](#reloading-in-rails-applications)
140
+ - [Rails 7+ (Zeitwerk)](#rails-7-zeitwerk)
141
+ - [Rails 6 and Earlier](#rails-6-and-earlier)
141
142
  - [Performance Monitoring](#performance-monitoring)
142
143
  - [Active Support Instrumentation](#active-support-instrumentation)
143
- - [endpoint_run.grape](#endpoint_rungrape)
144
- - [endpoint_render.grape](#endpoint_rendergrape)
145
- - [endpoint_run_filters.grape](#endpoint_run_filtersgrape)
146
- - [endpoint_run_validators.grape](#endpoint_run_validatorsgrape)
147
- - [format_response.grape](#format_responsegrape)
144
+ - [Hook Points](#hook-points)
145
+ - [endpoint_run.grape](#endpoint_rungrape)
146
+ - [endpoint_render.grape](#endpoint_rendergrape)
147
+ - [endpoint_run_filters.grape](#endpoint_run_filtersgrape)
148
+ - [endpoint_run_validators.grape](#endpoint_run_validatorsgrape)
149
+ - [format_response.grape](#format_responsegrape)
150
+ - [Subscribe to Hooks](#subscribe-to-hooks)
148
151
  - [Monitoring Products](#monitoring-products)
149
152
  - [Contributing to Grape](#contributing-to-grape)
150
153
  - [Security](#security)
@@ -157,14 +160,13 @@ Grape is a REST-like API framework for Ruby. It's designed to run on Rack or com
157
160
 
158
161
  ## Stable Release
159
162
 
160
- You're reading the documentation for the next release of Grape, 2.3.0.
161
- Please read [UPGRADING](UPGRADING.md) when upgrading from a previous version.
163
+ You're reading the documentation for the stable release of Grape, 3.0.0.
162
164
 
163
165
  ## Project Resources
164
166
 
165
167
  * [Grape Website](http://www.ruby-grape.org)
166
168
  * [Documentation](http://www.rubydoc.info/gems/grape)
167
- * Need help? Try [Grape Google Group](http://groups.google.com/group/ruby-grape) or [Gitter](https://gitter.im/ruby-grape/grape)
169
+ * Need help? [Open an Issue](https://github.com/ruby-grape/grape/issues)
168
170
  * [Follow us on Twitter](https://twitter.com/grapeframework)
169
171
 
170
172
  ## Grape for Enterprise
@@ -175,7 +177,7 @@ The maintainers of Grape are working with Tidelift to deliver commercial support
175
177
 
176
178
  ## Installation
177
179
 
178
- Ruby 2.7 or newer is required.
180
+ Ruby 3.0 or newer is required.
179
181
 
180
182
  Grape is available as a gem, to install it run:
181
183
 
@@ -272,7 +274,7 @@ Grape's [deprecator](https://api.rubyonrails.org/v7.1.0/classes/ActiveSupport/De
272
274
  ### All
273
275
 
274
276
 
275
- By default Grape will compile the routes on the first route, it is possible to pre-load routes using the `compile!` method.
277
+ By default Grape will compile the routes on the first route, but it is possible to pre-load routes using the `compile!` method.
276
278
 
277
279
  ```ruby
278
280
  Twitter::API.compile!
@@ -653,6 +655,27 @@ version 'v1', using: :param, parameter: 'v'
653
655
  curl http://localhost:9292/statuses/public_timeline?v=v1
654
656
 
655
657
 
658
+ ## Linting
659
+
660
+ You can check whether your API is in conformance with the [Rack's specification](https://github.com/rack/rack/blob/main/SPEC.rdoc) by calling `lint!` at the API level or through [configuration](#configuration).
661
+
662
+ ```ruby
663
+ class Api < Grape::API
664
+ lint!
665
+ end
666
+ ```
667
+ ```ruby
668
+ Grape.configure do |config|
669
+ config.lint = true
670
+ end
671
+ ```
672
+ ```ruby
673
+ Grape.config.lint = true
674
+ ```
675
+
676
+ ### Bug in Rack::ETag under Rack 3.X
677
+ If you're using Rack 3.X and the `Rack::Etag` middleware (used by [Rails](https://guides.rubyonrails.org/rails_on_rack.html#inspecting-middleware-stack)), a [bug](https://github.com/rack/rack/pull/2324) related to linting has been fixed in [3.1.13](https://github.com/rack/rack/blob/v3.1.13/CHANGELOG.md#3113---2025-04-13) and [3.0.15](https://github.com/rack/rack/blob/v3.1.13/CHANGELOG.md#3015---2025-04-13) respectively.
678
+
656
679
  ## Describing Methods
657
680
 
658
681
  You can add a description to API methods and namespaces. The description would be used by [grape-swagger][grape-swagger] to generate swagger compliant documentation.
@@ -719,10 +742,13 @@ For example, for the `param_builder`, the following code could run in an initial
719
742
 
720
743
  ```ruby
721
744
  Grape.configure do |config|
722
- config.param_builder = Grape::Extensions::Hashie::Mash::ParamBuilder
745
+ config.param_builder = :hashie_mash
723
746
  end
724
747
  ```
725
748
 
749
+ Available parameter builders are `:hash`, `:hash_with_indifferent_access`, and `:hashie_mash`.
750
+ See [params_builder](lib/grape/params_builder).
751
+
726
752
  You can also configure a single API:
727
753
 
728
754
  ```ruby
@@ -789,7 +815,7 @@ By default parameters are available as `ActiveSupport::HashWithIndifferentAccess
789
815
 
790
816
  ```ruby
791
817
  class API < Grape::API
792
- include Grape::Extensions::Hashie::Mash::ParamBuilder
818
+ build_with :hashie_mash
793
819
 
794
820
  params do
795
821
  optional :color, type: String
@@ -803,16 +829,15 @@ The class can also be overridden on individual parameter blocks using `build_wit
803
829
 
804
830
  ```ruby
805
831
  params do
806
- build_with Grape::Extensions::Hash::ParamBuilder
832
+ build_with :hash
807
833
  optional :color, type: String
808
834
  end
809
835
  ```
810
836
 
811
- Or globally with the [Configuration](#configuration) `Grape.configure.param_builder`.
812
-
813
837
  In the example above, `params["color"]` will return `nil` since `params` is a plain `Hash`.
814
838
 
815
- Available parameter builders are `Grape::Extensions::Hash::ParamBuilder`, `Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuilder` and `Grape::Extensions::Hashie::Mash::ParamBuilder`.
839
+ Available parameter builders are `:hash`, `:hash_with_indifferent_access`, and `:hashie_mash`.
840
+ See [params_builder](lib/grape/params_builder).
816
841
 
817
842
  ### Declared
818
843
 
@@ -4055,6 +4080,25 @@ Use [grape-reload](https://github.com/AlexYankee/grape-reload).
4055
4080
 
4056
4081
  ### Reloading in Rails Applications
4057
4082
 
4083
+ #### Rails 7+ (Zeitwerk)
4084
+
4085
+ Rails 7+ uses [Zeitwerk](https://github.com/fxn/zeitwerk) as the default autoloader, which automatically handles reloading of code in development mode without any additional configuration.
4086
+
4087
+ If your API files are in `app/api`, Zeitwerk will automatically autoload and reload them. No additional configuration is needed.
4088
+
4089
+ If you encounter issues with reloading, ensure that:
4090
+
4091
+ 1. Your API files follow Zeitwerk naming conventions (file names should match class names).
4092
+ 2. The `config.enable_reloading` is set to `true` in `config/environments/development.rb` (this is the default).
4093
+
4094
+ For troubleshooting autoloading issues, have a look at the [Rails documentation](https://guides.rubyonrails.org/autoloading_and_reloading_constants.html#troubleshooting).
4095
+
4096
+ See the [Rails Autoloading and Reloading Constants guide](https://guides.rubyonrails.org/autoloading_and_reloading_constants.html) for more information.
4097
+
4098
+ #### Rails 6 and Earlier
4099
+
4100
+ For Rails versions before 7, you need to configure reloading manually.
4101
+
4058
4102
  Add API paths to `config/application.rb`.
4059
4103
 
4060
4104
  ```ruby
@@ -4073,28 +4117,12 @@ if Rails.env.development?
4073
4117
  api_reloader = ActiveSupport::FileUpdateChecker.new(api_files) do
4074
4118
  Rails.application.reload_routes!
4075
4119
  end
4076
- ActionDispatch::Callbacks.to_prepare do
4120
+ ActiveSupport::Reloader.to_prepare do
4077
4121
  api_reloader.execute_if_updated
4078
4122
  end
4079
4123
  end
4080
4124
  ```
4081
4125
 
4082
- For Rails >= 5.1.4, change this:
4083
-
4084
- ```ruby
4085
- ActionDispatch::Callbacks.to_prepare do
4086
- api_reloader.execute_if_updated
4087
- end
4088
- ```
4089
-
4090
- to this:
4091
-
4092
- ```ruby
4093
- ActiveSupport::Reloader.to_prepare do
4094
- api_reloader.execute_if_updated
4095
- end
4096
- ```
4097
-
4098
4126
  See [StackOverflow #3282655](http://stackoverflow.com/questions/3282655/ruby-on-rails-3-reload-lib-directory-for-each-request/4368838#4368838) for more information.
4099
4127
 
4100
4128
  ## Performance Monitoring
@@ -4103,27 +4131,30 @@ See [StackOverflow #3282655](http://stackoverflow.com/questions/3282655/ruby-on-
4103
4131
 
4104
4132
  Grape has built-in support for [ActiveSupport::Notifications](http://api.rubyonrails.org/classes/ActiveSupport/Notifications.html) which provides simple hook points to instrument key parts of your application.
4105
4133
 
4106
- The following are currently supported:
4107
4134
 
4108
- #### endpoint_run.grape
4135
+ #### Hook Points
4136
+
4137
+ The following hook points are currently supported:
4138
+
4139
+ ##### endpoint_run.grape
4109
4140
 
4110
4141
  The main execution of an endpoint, includes filters and rendering.
4111
4142
 
4112
4143
  * *endpoint* - The endpoint instance
4113
4144
 
4114
- #### endpoint_render.grape
4145
+ ##### endpoint_render.grape
4115
4146
 
4116
4147
  The execution of the main content block of the endpoint.
4117
4148
 
4118
4149
  * *endpoint* - The endpoint instance
4119
4150
 
4120
- #### endpoint_run_filters.grape
4151
+ ##### endpoint_run_filters.grape
4121
4152
 
4122
4153
  * *endpoint* - The endpoint instance
4123
4154
  * *filters* - The filters being executed
4124
4155
  * *type* - The type of filters (before, before_validation, after_validation, after)
4125
4156
 
4126
- #### endpoint_run_validators.grape
4157
+ ##### endpoint_run_validators.grape
4127
4158
 
4128
4159
  The execution of validators.
4129
4160
 
@@ -4131,7 +4162,7 @@ The execution of validators.
4131
4162
  * *validators* - The validators being executed
4132
4163
  * *request* - The request being validated
4133
4164
 
4134
- #### format_response.grape
4165
+ ##### format_response.grape
4135
4166
 
4136
4167
  Serialization or template rendering.
4137
4168
 
@@ -4140,12 +4171,44 @@ Serialization or template rendering.
4140
4171
 
4141
4172
  See the [ActiveSupport::Notifications documentation](http://api.rubyonrails.org/classes/ActiveSupport/Notifications.html) for information on how to subscribe to these events.
4142
4173
 
4174
+ #### Subscribe to Hooks
4175
+
4176
+ Once subscribed to the instrumentation, you can intercept the events reported above.
4177
+
4178
+ ```ruby
4179
+ ActiveSupport::Notifications.subscribe(/<api_path>/) do |name, start, finish, id, payload|
4180
+ # your code to intercept the notification
4181
+ end
4182
+ ```
4183
+
4184
+ The request data, the API’s internal data, and the response can be retrieved from the payload.
4185
+
4186
+ You can use `payload.fetch(:endpoint)` or directly `payload[:endpoint]`.
4187
+
4188
+ The `:endpoint` contains the data currently being processed, and access to attributes such as `body`, `request`, `params`, `headers`, `cookies` and `response_cookies`
4189
+
4190
+ For example, `payload[:endpoint].body` provides the current state of the response.
4191
+
4192
+ ```ruby
4193
+ ActiveSupport::Notifications.subscribe(/v1/) do |name, start, finish, id, payload|
4194
+ hook_record = {
4195
+ hook: name
4196
+ status: payload[:env]&.dig("api.endpoint")&.status
4197
+ format: payload[:env]&.dig("api.format")
4198
+ body: payload[:endpoint]&.body
4199
+ duration: (finish - start) * 1000
4200
+ }
4201
+ # your code to save the notification
4202
+ end
4203
+ ```
4204
+
4143
4205
  ### Monitoring Products
4144
4206
 
4145
4207
  Grape integrates with following third-party tools:
4146
4208
 
4147
4209
  * **New Relic** - [built-in support](https://docs.newrelic.com/docs/agents/ruby-agent/frameworks/grape-instrumentation) from v3.10.0 of the official [newrelic_rpm](https://github.com/newrelic/rpm) gem, also [newrelic-grape](https://github.com/xinminlabs/newrelic-grape) gem
4148
4210
  * **Librato Metrics** - [grape-librato](https://github.com/seanmoon/grape-librato) gem
4211
+ * **Rails Performance** - [rails_performance](https://github.com/igorkasyanchuk/rails_performance) gem
4149
4212
  * **[Skylight](https://www.skylight.io/)** - [skylight](https://github.com/skylightio/skylight-ruby) gem, [documentation](https://docs.skylight.io/grape/)
4150
4213
  * **[AppSignal](https://www.appsignal.com)** - [appsignal-ruby](https://github.com/appsignal/appsignal-ruby) gem, [documentation](http://docs.appsignal.com/getting-started/supported-frameworks.html#grape)
4151
4214
  * **[ElasticAPM](https://www.elastic.co/products/apm)** - [elastic-apm](https://github.com/elastic/apm-agent-ruby) gem, [documentation](https://www.elastic.co/guide/en/apm/agent/ruby/3.x/getting-started-rack.html#getting-started-grape)
data/UPGRADING.md CHANGED
@@ -1,6 +1,95 @@
1
1
  Upgrading Grape
2
2
  ===============
3
3
 
4
+ ### Upgrading to >= 3.0.0
5
+
6
+ #### Ruby 3+ Argument Delegation Modernization
7
+
8
+ Grape has been modernized to use Ruby 3+'s preferred argument delegation patterns. This change replaces `args.extract_options!` with explicit `**kwargs` parameters throughout the codebase.
9
+
10
+ - All DSL methods now use explicit keyword arguments (`**kwargs`) instead of extracting options from mixed argument lists
11
+ - Method signatures are now more explicit and follow Ruby 3+ best practices
12
+ - The `active_support/core_ext/array/extract_options` dependency has been removed
13
+
14
+ This is a modernization effort that improves code quality while maintaining full backward compatibility.
15
+
16
+ See [#2618](https://github.com/ruby-grape/grape/pull/2618) for more information.
17
+
18
+ #### Configuration API Migration from ActiveSupport::Configurable to Dry::Configurable
19
+
20
+ Grape has migrated from `ActiveSupport::Configurable` to `Dry::Configurable` for its configuration system since its [deprecated](https://github.com/rails/rails/blob/1cdd190a25e483b65f1f25bbd0f13a25d696b461/activesupport/lib/active_support/configurable.rb#L3-L7).
21
+
22
+ See [#2617](https://github.com/ruby-grape/grape/pull/2617) for more information.
23
+
24
+ #### Endpoint execution simplified and `return` deprecated
25
+
26
+ Executing a endpoint's block has been simplified and calling `return` in it has been deprecated. Use `next` instead.
27
+
28
+ See [#2577](https://github.com/ruby-grape/grape/pull/2577) for more information.
29
+
30
+ #### Old Deprecations Clean Up
31
+
32
+ - `rack_response` has been removed in favor of using `error!`.
33
+ - `Grape::Exceptions::MissingGroupType` and `Grape::Exceptions::UnsupportedGroupType` aliases `MissingGroupTypeError and `UnsupportedGroupType` have been removed.
34
+ - `Grape::Validations::Base` has been removed in favor of `Grape::Validations::Validators::Base`.
35
+
36
+ See [2573](https://github.com/ruby-grape/grape/pull/2573) for more information.
37
+
38
+ ### Upgrading to >= 2.4.0
39
+
40
+ #### Grape::Middleware::Auth::Base
41
+ `type` is now validated at compile time and will raise a `Grape::Exceptions::UnknownAuthStrategy` if unknown.
42
+
43
+ #### Grape::Middleware::Base
44
+
45
+ - Second argument `options` is now a double splat (**) instead of single splat (*). If you're redefining `initialize` in your middleware and/or calling `super` in it, you might have to adapt the signature and the `super` call. Also, you might have to remove `{}` if you're pass `options` as a literal `Hash` or add `**` if you're using a variable.
46
+ - `Grape::Middleware::Helpers` has been removed. The equivalent method `context` is now part of `Grape::Middleware::Base`.
47
+
48
+ #### Grape::Http::Headers, Grape::Util::Lazy::Object
49
+
50
+ Both have been removed. See [2554](https://github.com/ruby-grape/grape/pull/2554).
51
+ Here are the notable changes:
52
+
53
+ - Constants like `HTTP_ACCEPT` have been replaced by their literal value.
54
+ - `SUPPORTED_METHODS` has been moved to `Grape` module.
55
+ - `HTTP_HEADERS` has been moved to `Grape::Request` and renamed `KNOWN_HEADERS`. The last has been refreshed with new headers, and it's not lazy anymore.
56
+ - `SUPPORTED_METHODS_WITHOUT_OPTIONS` and `find_supported_method` have been removed.
57
+
58
+ #### Grape::Middleware::Base
59
+
60
+ - Constant `TEXT_HTML` has been removed in favor of using literal string 'text/html'.
61
+ - `rack_request` and `query_params` have been added. Feel free to call these in your middlewares.
62
+
63
+ #### Params Builder
64
+
65
+ - Passing a class to `build_with` or `Grape.config.param_builder` has been deprecated in favor of a symbolized short_name. See `SHORTNAME_LOOKUP` in [params_builder](lib/grape/params_builder.rb).
66
+ - Including Grape's extensions like `Grape::Extensions::Hashie::Mash::ParamBuilder` has been deprecated in favor of using `build_with` at the route level.
67
+
68
+ #### Accept Header Negotiation Harmonized
69
+
70
+ [Accept](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Accept) header is now fully interpreted through `Rack::Utils.best_q_match` which is following [RFC2616 14.1](https://datatracker.ietf.org/doc/html/rfc2616#section-14.1). Since [Grape 2.1.0](https://github.com/ruby-grape/grape/blob/master/CHANGELOG.md#210-20240615), the [header versioning strategy](https://github.com/ruby-grape/grape?tab=readme-ov-file#header) was adhering to it, but `Grape::Middleware::Formatter` never did.
71
+
72
+ Your API might act differently since it will strictly follow the [RFC2616 14.1](https://datatracker.ietf.org/doc/html/rfc2616#section-14.1) when interpreting the `Accept` header. Here are the differences:
73
+
74
+ ##### Invalid or missing quality ranking
75
+ The following used to yield `application/xml` and now will yield `application/json` as the preferred media type:
76
+ - `application/json;q=invalid,application/xml;q=0.5`
77
+ - `application/json,application/xml;q=1.0`
78
+
79
+ For the invalid case, the value `invalid` was automatically `to_f` and `invalid.to_f` equals `0.0`. Now, since it doesn't match [Rack's regex](https://github.com/rack/rack/blob/3-1-stable/lib/rack/utils.rb#L138), its interpreted as non provided and its quality ranking equals 1.0.
80
+
81
+ For the non provided case, 1.0 was automatically assigned and in a case of multiple best matches, the first was returned based on Ruby's sort_by `quality`. Now, 1.0 is still assigned and the last is returned in case of multiple best matches. See [Rack's implementation](https://github.com/rack/rack/blob/e8f47608668d507e0f231a932fa37c9ca551c0a5/lib/rack/utils.rb#L167) of the RFC.
82
+
83
+ ##### Considering the closest generic when vendor tree
84
+ Excluding the [header versioning strategy](https://github.com/ruby-grape/grape?tab=readme-ov-file#header), whenever a media type with the [vendor tree](https://datatracker.ietf.org/doc/html/rfc6838#section-3.2) leading facet `vnd.` like `application/vnd.api+json` was provided, Grape would also consider its closest generic when negotiating. In that case, `application/json` was added to the negotiation. Now, it will just consider the provided media types without considering any closest generics, and you'll need to [register](https://github.com/ruby-grape/grape?tab=readme-ov-file#api-formats) it.
85
+ You can find the official vendor tree registrations on [IANA](https://www.iana.org/assignments/media-types/media-types.xhtml)
86
+
87
+ #### Custom Validators
88
+
89
+ If you now receive an error of `'Grape::Validations.require_validator': unknown validator: your_custom_validation (Grape::Exceptions::UnknownValidator)` after upgrading to 2.4.0 then you will need to ensure that you require the `your_custom_validation` file before your Grape API code is loaded.
90
+
91
+ See [2533](https://github.com/ruby-grape/grape/issues/2533) for more information.
92
+
4
93
  ### Upgrading to >= 2.3.0
5
94
 
6
95
  ### `content_type` vs `api.format` inside API
@@ -83,7 +172,7 @@ When using together with `Grape::Extensions::Hash::ParamBuilder`, `route_param`
83
172
  This was a regression introduced by [#2326](https://github.com/ruby-grape/grape/pull/2326) in Grape v1.8.0.
84
173
 
85
174
  ```ruby
86
- grape.configure do |config|
175
+ Grape.configure do |config|
87
176
  config.param_builder = Grape::Extensions::Hash::ParamBuilder
88
177
  end
89
178
 
data/grape.gemspec CHANGED
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- $LOAD_PATH.unshift File.expand_path('lib', __dir__)
4
- require 'grape/version'
3
+ require_relative 'lib/grape/version'
5
4
 
6
5
  Gem::Specification.new do |s|
7
6
  s.name = 'grape'
@@ -21,7 +20,8 @@ Gem::Specification.new do |s|
21
20
  'rubygems_mfa_required' => 'true'
22
21
  }
23
22
 
24
- s.add_dependency 'activesupport', '>= 6'
23
+ s.add_dependency 'activesupport', '>= 7.0'
24
+ s.add_dependency 'dry-configurable'
25
25
  s.add_dependency 'dry-types', '>= 1.1'
26
26
  s.add_dependency 'mustermann-grape', '~> 1.1.0'
27
27
  s.add_dependency 'rack', '>= 2'
@@ -29,5 +29,5 @@ Gem::Specification.new do |s|
29
29
 
30
30
  s.files = Dir['lib/**/*', 'CHANGELOG.md', 'CONTRIBUTING.md', 'README.md', 'grape.png', 'UPGRADING.md', 'LICENSE', 'grape.gemspec']
31
31
  s.require_paths = ['lib']
32
- s.required_ruby_version = '>= 2.7.0'
32
+ s.required_ruby_version = '>= 3.0'
33
33
  end