Skip to content

Fix request_path being replaced by a named route helper (supersedes #3) - #19

Merged
jlsync merged 2 commits into
masterfrom
fix-request-path-collision
Oct 10, 2026
Merged

jlsync merged 2 commits into
masterfrom
fix-request-path-collision

Conversation

@jlsync

@jlsync jlsync commented Oct 10, 2026 •

Copy link
Copy Markdown
Collaborator

Supersedes #3. The diagnosis is @rst's (Robert Thau's) — he reported this in 2010 with a patch that renamed the method to path_of_request. This is that idea rebased onto the current code; the credit is his.

The problem

resources :requests generates a member route helper called request_path. Rails includes the generated url_helpers module into controllers after resources_controller's modules, so it wins the method lookup:

module ancestor index (lower wins)
url_helpers (defines request_path) 7
ResourcesController::RequestPathIntrospection (has its own request_path) 12

RequestPathIntrospection calls request_path internally (nesting_request_path, namespace_segments), so with such a route present it read the helper's value instead of params[:resource_path] || request.path. The real request path was lost, so enclosing resources were not detected — and the invented path was then fed to the wildcard loader, so unrelated controllers tried to load resources that were not part of the request.

Measured on master (Ruby 4.0.7, Rails 8.1.4) with a top level resources :requests added to spec/app.rb:

spec/lib/request_path_introspection_spec.rb whole suite
master + the route 16 examples, 6 failures 666 examples, 513 failures
this branch + the route 17 examples, 0 failures 667 examples, 0 failures

The fix

  • RequestPathIntrospection#request_path is renamed to #rc_request_path (its ivars with it), and the caller in raise_resource_mismatch is updated. #nesting_request_path is left alone: no plausible route is named that.
  • 24 spec call sites updated across 6 files.
  • New regression spec includes a module that defines a public request_path into the controller under test — the position url_helpers occupies — and asserts the path of the request is still read. It fails on master with "the shadowing route helper was called" and passes here.
  • v5.0.0 is tagged at the PR Non-invasive performance improvements and route helper optimizations #18 merge (815250a), so the CHANGELOG entry goes in a new 5.0.1 section and VERSION is bumped to 5.0.1. The README.rdoc → README.md note moved there too, since that landed on master after the tag.

Note for anyone overriding request_path

#request_path was protected and undocumented, but an app may have overridden it to customise the path; that no longer works. The documented mechanism is unchanged: pass :resource_path in the route (see the docs in lib/resources_controller.rb), or override #rc_request_path.

bundle exec rspec → 667 examples, 0 failures, and gem build produces rc_rails-5.0.1 without warnings.

jlsync and others added 2 commits October 10, 2026 09:39
A route like `resources :requests` generates a public `request_path` helper, and
Rails includes the url_helpers module into controllers after
resources_controller's modules (url_helpers sits at ancestor index 7,
RequestPathIntrospection at 12, and the lower index wins).  resources_controller's
own request_path was therefore replaced by the route helper, so it read the
helper's value instead of the path of the current request, and could not work out
the enclosing resources: with a top level `resources :requests` route in the spec
app, 6 examples in spec/lib/request_path_introspection_spec.rb fail.

The internal reader is renamed to rc_request_path, so that no plausible route name
can collide with it, and the specs are updated to match.

Based on PR #3 by Robert Thau, which diagnosed this and proposed the same rename
(as path_of_request) but is written against the pre-rename lib/ardes/ layout and
RSpec 2 syntax, so it no longer applies.

Adds a regression spec that includes a module defining a public request_path into
the controller under test - the position url_helpers occupies - and asserts the
path of the request is still read.

Co-authored-by: DeepSeek <agent@deepseek.com>
v5.0.0 is tagged at the PR #18 merge, so the two changes that landed on master
after the tag get their own section: this request_path fix, and the README.rdoc to
README.md conversion (which was pushed in 1db30bb, after the tag).

Bumps VERSION to 5.0.1 so that version.rb, the gemspec and the CHANGELOG agree.

Co-authored-by: DeepSeek <agent@deepseek.com>
@jlsync
jlsync merged commit f7a6b38 into master Oct 10, 2026
6 checks passed
@jlsync
jlsync deleted the fix-request-path-collision branch October 10, 2026 08:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant