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
{{ message }}
Repository navigation
Commit 67f619d
Browse filesBrowse the repository at this point in the historyBrowse files
Make a helper reach the routes declared above it in its scope
An endpoint is built from a point-in-time copy of its scope's settings.
The copy keeps the scope's own helpers as they were at the route, but
links to the enclosing scopes live. So a `helpers` declared further
down the same scope never reached the route, and calling it raised
NameError. One declared further down an enclosing scope, or after
`mount`, did reach it.
The endpoint now also keeps the live settings of its scope and reads
the helpers from them when it compiles, by which time the whole class
body has run. A helper declared in a sibling namespace still doesn't
reach the route.
A helper defined twice in one scope therefore answers with its last
definition in every route of that scope, including those declared
between the two definitions. UPGRADING describes that change. The
README no longer lists `helpers` among the declarations that must come
above the routes they cover. `use`, `rescue_from` and the callbacks are
unchanged.
The route endpoint gains a sixth ivar. Per-request copies hold eight,
so their 80-byte slot is unchanged.
Fixes#34
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: CHANGELOG.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -17,6 +17,7 @@
17
17
*[#3051](https://github.com/ruby-grape/grape/pull/3051): Look up the validation error format once per response instead of once per message - [@ericproulx](https://github.com/ericproulx).
18
18
*[#3055](https://github.com/ruby-grape/grape/pull/3055): Stop a 405 behind `Rack::Cascade` from making the next app answer 405 too - [@ericproulx](https://github.com/ericproulx).
19
19
*[#3058](https://github.com/ruby-grape/grape/pull/3058): Declare `rexml` in the test bundle instead of relying on Danger to bring it in - [@ericproulx](https://github.com/ericproulx).
20
+
*[#3061](https://github.com/ruby-grape/grape/pull/3061): Make a helper reach the routes declared above it in its scope - [@ericproulx](https://github.com/ericproulx).
Copy file name to clipboardExpand all lines: README.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2874,7 +2874,7 @@ class Twitter::API < Grape::API
2874
2874
end
2875
2875
```
2876
2876
2877
-
The same goes for `use`, `helpers`and the `before`/`after` callbacks.
2877
+
The same goes for `use`and the `before`/`after` callbacks. `helpers` are the exception: they reach every route of their scope, wherever they are declared in it.
2878
2878
2879
2879
Notice that you could combine these two approaches (rescuing custom errors takes precedence). For example, it's useful for handling all exceptions except Grape validation errors.
Copy file name to clipboardExpand all lines: UPGRADING.md
+15Lines changed: 15 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -3,6 +3,21 @@ Upgrading Grape
3
3
4
4
### Upgrading to >= 4.2.0
5
5
6
+
#### A helper reaches every route of its scope, wherever it is declared
7
+
8
+
A `helpers` block or module used to reach only the routes declared below it in the same scope. A route declared above it raised `NameError` when it called the helper ([#34](https://github.com/ruby-grape/grape/issues/34)). Since [#3061](https://github.com/ruby-grape/grape/pull/3061) it reaches every route of its scope, as it already did from an enclosing scope and through `mount`.
9
+
10
+
So a helper method defined twice in one scope now answers with its last definition in every route of that scope, including the routes declared between the two definitions:
11
+
12
+
```ruby
13
+
helpers { defgreeting='first' }
14
+
get('/before') { greeting } # was 'first', now 'second'
15
+
helpers { defgreeting='second' }
16
+
get('/after') { greeting } # 'second'
17
+
```
18
+
19
+
To keep a different method per route, give the methods different names, or declare the routes in separate namespaces, each with its own `helpers`. `use`, `rescue_from` and the `before`/`after` callbacks still apply only to the routes declared below them.
20
+
6
21
#### A request every route declines answers 404, however many routes declined
7
22
8
23
A route declines a request by answering with `X-Cascade: pass`, as a version declared with `cascade: true` does for a version it does not serve. As the [README](README.md#header) documents, the router then answers its own `404` if no other route takes the request. It only did so when one route had declined: with two or more routes on the path, the last one's response came back instead, and so did that of an ANY route (since 4.0.0). So a request for an unknown version answered `404` from an API with one version and `406` from an API with several.
0 commit comments