我正在使用Rails引擎的Ruby on Rails 3(.0)应用程序。但是,在我的本地应用程序中,我想覆盖Rails引擎提供的其中一个路由。
来自引擎config / routes.rb:
match 'their_named_route' => 'controller#action', :as => 'the_route'
从我的应用程序config / routes.rb:
match 'my_named_route' => 'controller#action', :as => 'the_route'
然而,当我检查路线时,两者似乎都是活动的(并且它们的路线似乎“赢”,至少在引擎控制器内)
$ rake routes
the_route /my_named_route(.:format) {:controller=>"controller", :action=>"action"}
the_route /their_named_route(.:format) {:controller=>"controller", :action=>"action"}
有没有一种方法可以强制我的本地应用程序的命名路由优先?
答案 0 :(得分:8)
我通过将引擎的路由从config / routes.rb移动到引擎类本身的类方法来解决这个问题:
module MyEngine
class Engine < Rails::Engine
def self.routes
MyRailsApp::Application.routes.draw do
resources :products
end
end
end
end
然后在基本应用程序的路径文件中:
MyRailsApp::Application.routes.draw do
# Routes for base app including the ones overriding MyEngine::Engine.
MyEngine::Engine.routes
end
然后我可以愉快地覆盖基础应用程序中的任何路径与引擎中的路由。
请注意,覆盖路由需要在覆盖路由之前定义,因为先前定义的路由优先于后面的路由。
答案 1 :(得分:6)
我担心没有这么简单的方法。路由在lib/action_dispatch/routing/mapper.rb:271
中定义,它在RouteSet上调用add_route(在rack-mount-0.6.14/lib/rack/mount/route_set.rb
中定义,在第71行上附加名称)。没有remove_route方法,最后添加了Engine的路由。使用Rails.application.routes.draw初始化应用程序后,您可以手动添加路由,而不是在routes.rb中使用它,或者您可以修补引擎。
答案 2 :(得分:4)
无法覆盖引擎内的路由。相反,您必须定义一个覆盖路线。您可以通过在引擎的路由器上调用prepend
来执行此操作:
An::Engine.routes.prepend do
root :to => "somewhere#action"
end
如果引擎的命名空间是隔离的,那么它将使用引擎命名空间内的SomewhereController
。如果没有,它将使用典型的SomewhereController
。
如果要覆盖路由以返回404,我能想到的最好方法是重定向到404页面:
match "/route_goes_here" => redirect("/404")
答案 3 :(得分:2)
您需要为config / application.rb添加初始化程序挂钩,如下所示:
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
首先加载你引擎的roues.rb,你可以覆盖他们的路线。
答案 4 :(得分:2)
您可以按照上面Ryan Bigg的建议预先添加路线。我发现,为了用我的自定义路线否决指定的路线助手,我需要拨打append
而不是prepend
,如下所示:
An::Engine.routes.append do
root :to => "somewhere#action"
end
否则,应用程序包含两个路由,引擎路由器的命名助手是最后一个定义,因此是应用的路径。
答案 5 :(得分:1)
routes.rb中定义的路由规则从上到下应用,直到找到匹配项。只需将优先级较高的规则移动到上安装引擎的行,我就可以覆盖已安装引擎中定义的路由。所以,
get 'about', controller: 'static', action: 'about', as: 'about'
mount My::Engine => '/'
&#13;
导致应用程序路由/关于/请求(在本例中)为静态控制器,而:
mount My::Engine => '/'
get 'about', controller: 'static', action: 'about', as: 'about'
&#13;
导致应用程序路由/ about / requests到已挂载引擎中定义的路由。