rails/rails — pull request #3861 by andyjeffries (2011-12-05 15:46:12+00:00)
Title: Named Routes shouldn't override existing ones (currently route recognition goes with the earliest match, named routes use the latest match)

Our application is built up of multiple engines and on the whole works very well. I'll give an example of a problem we're having though. We have a gem (Engine) that has this in it:

calendar_gem/config/routes.rb:
Rails.application.routes.draw do
get '/calendar' => 'our_framework/calendar#index', :as => :our_framework_calendar
end

We then use this named route within the gem (and other gems, and the application itself). We use Rails.application because we don't know the specific application class the gem will be used in. This works fine and if we want to override the controller/action in our applications (to have some custom calendar for them), it's as simple as:

app/config/routes.rb:
OurApp::Application.routes.draw do
get '/calendar' => 'calendar#index', :as => :our_framework_calendar
end

This works for us because application routes are loaded before gem routes, therefore the routing shortcuts at the first match when the user visits /calendar and it never gets to the gem's route.

The problem comes when we want to change not the dispatch point, but the actual URL generated for that named path (our customer, a large client, has a very strict requirements on what they want the URLs to be and we don't want to change it in the gem as it's used for all customers). If we do this in our application:

app/config/routes.rb:
OurApp::Application.routes.draw do
get '/agenda' => 'our_framework/calendar#index', :as => :our_framework_calendar
end

The application recognises /agenda as the correct URL, but when we call our_framework_calendar_path (as we use this in lots of places, including shared code) it uses the gem's choice of URL.

It seems illogical that url matching uses first match, but named_paths uses last match. This pull request reverses it.