Rails 4.0 patterns: routing entries (duplicate roots, controller names, route-file modules)#103
Open
JuanVqz wants to merge 3 commits into
Open
Rails 4.0 patterns: routing entries (duplicate roots, controller names, route-file modules)#103JuanVqz wants to merge 3 commits into
JuanVqz wants to merge 3 commits into
Conversation
Rails 4 raises ArgumentError: Invalid route name, already in use: 'root' when the routes file has more than one `root` declaration (typically one per constraint block). Rails 3.2 was lenient about duplicate names with different constraints, so this slips through on many 3.x codebases. The naive fix — give each duplicate an `as:` — silently breaks every root_path / root_url caller in the codebase because the :root name is no longer registered to any declaration. Real apps have dozens to hundreds of these helper calls in controllers, views, mailers, and tests. Correct fix: keep the FIRST declaration as the default :root, only add `as:` to the SECOND and subsequent. Includes a grep verification step so operators confirm no caller targets a constraint-bound root that was renamed. Classified high_priority / kind: breaking — Rails 4 boot raises outright on the duplicate.
Rails 4 validates controller names in `to:` clauses with strict rules: no hyphens, no CamelCase. Hyphenated values raise ArgumentError: 'foo-bar' is not a supported controller name; the CamelCase form raises the same error. Rails 3.2 was lenient and auto-normalized. Common shapes that trigger the regex: get "/", to: "my-pages#show" # hyphen get "/", to: "MyPages#show" # CamelCase URL paths (the route path itself) can keep hyphens — only the controller class reference in `to:` needs to be snake_case. The fix field calls this out so operators don't accidentally rewrite path strings. The snake_case form resolves to the same controller class on Rails 3.2, so the rewrite ships pre-bump and is backwards-compatible. Classified high_priority / kind: breaking — Rails 4 boot raises on the bad name.
Rails 4's route loader does not reliably persist top-level module
definitions across the routes-reload boundary. A pattern like
module Constraints
class Admin
...
end
end
defined inside a config/routes/*.rb file may evaluate at boot but
the Constraints constant does not survive subsequent reloads, and
downstream uses like `constraints Constraints::Admin do ... end`
raise NameError: uninitialized constant Constraints. Rails 3.2
handled this more leniently — modules defined in route files
persisted across reload boundaries.
Fix is two-part, branched on NextRails.next?:
1. Move the module's class definitions to convention paths
(e.g. config/routes/constraints/admin.rb for Constraints::Admin)
so Rails autoload finds them.
2. Add the parent directory to config.autoload_paths, also gated by
NextRails.next?, so the new layout only applies on the Rails 4+
side. Rails 3.2 still wants the modules at the original path
inside the route file.
The exclude regex skips RSpec:: and Constraints:: references that
match the leading `module` pattern but are not actual module
definitions.
Classified high_priority / kind: breaking — Rails 4 raises NameError
on the first reload that hits the dropped constant.
1a0aaa9 to
0a1c21e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three new Rails 4.0 routing patterns that boot-fail or break callers, currently undetected by the OSS skill.
ArgumentError: Invalid route name, already in use: 'root'on the secondrootdeclaration. The naive fix (give each duplicate anas:) silently breaks everyroot_path/root_urlcaller; fix keeps the FIRST as default:rootand renames only the rest. Includes a grep verification step.ArgumentError: 'foo-bar' is not a supported controller namefor hyphenated or CamelCaseto:values. URL paths are unaffected. snake_case rewrite is backwards-compatible on 3.2.NameErroron reload. Two-part fix branched onNextRails.next?(move classes to convention paths + addconfig.autoload_paths).All three classified
high_priority/kind: breaking. Boot-fatal on Rails 4.Test plan
bin/validate-patterns rails-upgrade/detection-scripts/patterns/rails-40-patterns.ymlclean.