I am working on a Ruby on Rails 3(.0) application that uses a Rails engine. However, in my local application, I want to override one of the routes provided by the Rails engine.
From the engine config/routes.rb:
match 'their_named_route' => 'controller#action', :as => 'the_route'
From my application config/routes.rb:
match 'my_named_route' => 'controller#action', :as => 'the_route'
However, when I inspect the routes, both seem to be active (and their route appears to "win", at least within the engine controllers)
$ rake routes
the_route /my_named_route(.:format) {:controller=>"controller", :action=>"action"}
the_route /their_named_route(.:format) {:controller=>"controller", :action=>"action"}
Is there a good way to force my local application's named route to take priority?
I got around this by moving my engine's routes from config/routes.rb to a class method in the engine class itself:
module MyEngine
class Engine < Rails::Engine
def self.routes
MyRailsApp::Application.routes.draw do
resources :products
end
end
end
end
and then in the base app's routes file:
MyRailsApp::Application.routes.draw do
# Routes for base app including the ones overriding MyEngine::Engine.
MyEngine::Engine.routes
end
I can then happily override any routes in the base app with those in the engine.
Note that the overriding routes need to be defined before the overridden routes since the earlier defined routes take precedence over later ones.
I'm afraid that there's no such easy way. The routes are defined in lib/action_dispatch/routing/mapper.rb:271
, which calls add_route on the RouteSet (defined in rack-mount-0.6.14/lib/rack/mount/route_set.rb
, and on line 71 the name is attached). There's no remove_route method, and the Engine's route is added last. You can add your route manually after the application is initialized with Rails.application.routes.draw instead of having it in routes.rb, or you can patch the Engine.
There is no way to override a route within an engine. Instead, you must define an overruling route. You can do this by calling prepend
on the engine's router:
An::Engine.routes.prepend do
root :to => "somewhere#action"
end
If the engine's namespace is isolated, this will use the SomewhereController
from inside the engine's namespace. If not, it will use the typical SomewhereController
.
If you want to override a route to return a 404, the best way I can think of is to redirect to a 404 page:
match "/route_goes_here" => redirect("/404")
You need add initializer hook to config/application.rb, like this:
class Application < Rails::Application
config.encoding = "utf-8"
...
initializer :add_routing_paths do |app|
their_routes_path = app.routes_reloader.paths.select{|path| path =~ /DIR/}.first
app.routes_reloader.paths.delete(their_routes_path)
app.routes_reloader.paths.unshift(their_routes_path)
end
end
It's load roues.rb of you engine first and you can override their routes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With