You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* Pass http_methods to Grape::Endpoint as a keyword instead of via options
`method` was pulled out of the endpoint's `**options` Hash, normalized in
place (`@options[:method] = Array(...)`), and renamed to `http_methods` on
the `Options` value object purely to dodge the `Object#method` shadow on
the generated Data accessor.
Expose it directly as a required `http_methods:` keyword on
`Grape::Endpoint#initialize` and pass it straight into `Options`, whose
field is now genuinely named `http_methods` (no rename, no shadow). The
value stays in `config` so endpoint equality — `config == other.config`,
which keeps same-path/different-verb endpoints distinct — is unchanged.
The endpoint's public `options` Hash no longer carries the redundant
`:method` entry; nothing read it, and grape-swagger reads the verb from
`route.request_method`. Documented in UPGRADING.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Pass path to Grape::Endpoint as a keyword instead of via options
`path` was pulled from the endpoint's `**options` Hash and normalized in
place (`@options[:path] = Array(...)`), duplicating the normalization
`Options` already does.
Expose it as a required `path:` keyword on `Grape::Endpoint#initialize`
and pass it straight into `Options`, which stays the single normalized
source of truth. `path` remains in `config` because it is load-bearing
for route building (`config.path`) and for endpoint equality
(`config == other.config`, which keeps same-path/different-verb endpoints
distinct).
The endpoint's public `options` Hash no longer carries `:path`. Its only
reader was an internal test; `route.path` (the compiled pattern) is the
public path API and is what grape-swagger already uses. Documented in
UPGRADING.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Add mounted_app reader and app: keyword to Grape::Endpoint
`app` (the Rack app or Grape API mounted at an endpoint) was reachable
only by digging into the public options bag as `endpoint.options[:app]`.
Introduce a first-class `mounted_app` reader (returning `config.app`,
`nil` for a plain block endpoint) and accept `app:` as an explicit
keyword on `Grape::Endpoint#initialize`. Grape's own mount-refresh dedup
now reads `endpoint.mounted_app` instead of `options[:app]`.
This is additive and non-breaking: `options[:app]` is still populated
exactly as before for downstream consumers (e.g. grape-swagger), which
can migrate to `mounted_app` before it is eventually dropped from the
options Hash. Also adds the previously-missing coverage for the
`refresh_already_mounted` dedup path.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Rename Grape::Endpoint's for: keyword to api: and expose #api
`for` identified the API an endpoint belongs to, but it is a reserved
word: it can only reach `Options` through `**rest` and its value can't be
referenced as a local. Rename it to `api:`, an explicit keyword on
`Grape::Endpoint#initialize`, and drop the `**rest` workaround from
`Options`.
`api` stays in `config` because it is load-bearing: the endpoint reaches
the mounting API's live `configuration` (used by remountable APIs and
read lazily at request time) through it, so it cannot be captured at
construction. `logger` and the new public `#api` reader are exposed via
`Forwardable` delegation to the config value object.
The owning API is no longer carried on the endpoint's public options Hash
(`endpoint.options[:for]` is gone); use `endpoint.api` instead. Only
in-repo reader was one spec. Documented in UPGRADING.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Promote route metadata to Route keyword arguments
`version`, `namespace`, `prefix`, `requirements`, `anchor` and `settings`
were computed in `Endpoint#prepare_default_route_attributes`, merged into
the route options Hash, and read back through `Grape::Router::BaseRoute`'s
`def_delegators :@options`. They are route metadata, not part of the
user-declared options bag grape-swagger consumes.
They are now passed to `Grape::Router::Route` as explicit keyword
arguments and exposed as plain readers on `BaseRoute`. `Endpoint#to_routes`
computes each as a local and passes `config.route_options` straight
through, so `prepare_default_route_attributes` (and the intermediate
`default_route_options`/`complete_route_options`) is gone. `Route`
forwards the attributes to `super` via `**route_attributes` to keep its
signature lean.
`route.options` now carries only what was declared for the route; the
`@options` delegation is down to `description` plus the documentation
`DSL_METHODS`. The readers are unchanged, so grape-swagger (which reads
`route.prefix` and `route.settings`) is unaffected. `requirements` and
`anchor` can still be declared as route options, so any explicit value
stays in `route.options`; the effective value comes from the reader.
Also drop the vestigial `:format` member from the endpoint's `Options`.
Nothing ever passed `format:` to `Grape::Endpoint.new`, so `config.format`
was always `nil`; the format capture comes from the path suffix built by
`Grape::Path`, not from `Pattern`'s `format`. `Pattern#initialize` keeps
`format:` (now optional) since it remains a valid capture constraint used
by external callers.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
*[#2774](https://github.com/ruby-grape/grape/pull/2774): Make `forward_match` an internal kwarg instead of a route option - [@ericproulx](https://github.com/ericproulx).
7
+
*[#2775](https://github.com/ruby-grape/grape/pull/2775): Pass `http_methods` to `Grape::Endpoint` as a keyword instead of via options - [@ericproulx](https://github.com/ericproulx).
8
+
*[#2776](https://github.com/ruby-grape/grape/pull/2776): Pass `path` to `Grape::Endpoint` as a keyword instead of via options - [@ericproulx](https://github.com/ericproulx).
9
+
*[#2777](https://github.com/ruby-grape/grape/pull/2777): Add `Grape::Endpoint#mounted_app` reader and `app:` keyword - [@ericproulx](https://github.com/ericproulx).
10
+
*[#2778](https://github.com/ruby-grape/grape/pull/2778): Rename `Grape::Endpoint`'s `for:` keyword to `api:` and expose `#api` - [@ericproulx](https://github.com/ericproulx).
Copy file name to clipboardExpand all lines: UPGRADING.md
+45Lines changed: 45 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,6 +9,51 @@ Upgrading Grape
9
9
10
10
As a result it is no longer readable through `route.options[:forward_match]` or the `route.forward_match` reader — both previously returned the flag. Nothing in Grape consumed either, so this only affects code that introspected routes directly; there is no replacement, as the value is now purely internal.
11
11
12
+
#### `Grape::Endpoint.new` takes `http_methods:` instead of `method:`
13
+
14
+
`Grape::Endpoint.new` now receives the HTTP verb(s) under the `http_methods:` keyword instead of `method:`, matching the name used everywhere else. If you build endpoints directly (uncommon — this is an internal API normally driven by the routing DSL), rename the keyword:
Relatedly, an endpoint's public `options` Hash no longer carries `:method` or `:path`. Nothing in Grape read `:method`, and the only reader of `:path` was an internal test; both values are available from the route instead — `route.request_method` for the verb and `route.path` for the (compiled) path, which is what grape-swagger and other introspection already use. The raw definition-time path array is no longer exposed on the endpoint.
25
+
26
+
#### `Grape::Endpoint.new` takes `api:` instead of `for:`
27
+
28
+
The keyword identifying the API an endpoint belongs to has been renamed from `for:` — a reserved word whose value can't be referenced as a local — to `api:`:
The owning API is no longer carried on the endpoint's public `options` Hash — `endpoint.options[:for]` is gone. Use the new `endpoint.api` reader instead.
39
+
40
+
#### Route metadata is exposed through readers, not the `options` Hash
41
+
42
+
A route's computed metadata — `version`, `namespace`, `prefix`, `requirements`, `anchor` and `settings` — is now passed to `Grape::Router::Route` as explicit keyword arguments and exposed as plain readers, instead of being merged into the route's `options` Hash.
43
+
44
+
The readers are unchanged — keep using them:
45
+
46
+
```ruby
47
+
route.version # => 'v1'
48
+
route.namespace # => '/things'
49
+
route.prefix # => 'api'
50
+
route.requirements # => {}
51
+
route.anchor # => true
52
+
route.settings # => { ... }
53
+
```
54
+
55
+
What changed is the raw bag. `route.options` now holds only what was declared for the route, so it no longer carries the *computed* values for these keys — `route.options[:version]`, `[:namespace]`, `[:prefix]` and `[:settings]` return `nil`. Nothing in Grape or grape-swagger read them that way (grape-swagger uses the `route.prefix` and `route.settings` readers). For `requirements` and `anchor`, which can be supplied as route options (e.g. a mount's `anchor: false`), any explicitly declared value still appears in `route.options`; the effective value always comes from the reader.
0 commit comments