Overriding named routes provided by Rails 3 Engines

◇◆丶佛笑我妖孽 提交于 2019-12-18 21:49:51

问题


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?


回答1:


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.




回答2:


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.




回答3:


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")



回答4:


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.




回答5:


You can prepend routes as suggest by Ryan Bigg above. I found that in order overrule the named route helper with my custom route I need to call append instead of prepend, like so:

An::Engine.routes.append do
  root :to => "somewhere#action"
end

Otherwise the app contains both routes and the named helper for engine's router is the last definition, and therefore the one that is applied.




回答6:


Routing rules defined in routes.rb are applied from the top down until a match is found. I was able to override the route defined in the mounted engine simply by moving the higher-priority rule above the line where the engine is mounted. So,

get 'about', controller: 'static', action: 'about', as: 'about'
mount My::Engine => '/'

results in the app routing /about/ requests to (in this case) the static controller, whereas:

mount My::Engine => '/'
get 'about', controller: 'static', action: 'about', as: 'about'

results in the app routing /about/ requests to the route defined in the mounted engine.



来源:https://stackoverflow.com/questions/5997527/overriding-named-routes-provided-by-rails-3-engines

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!