覆盖Rails 3 Engines提供的命名路由

时间:2011-05-13 20:40:02

标签: ruby-on-rails ruby-on-rails-3 routes rails-engines

我正在使用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"}

有没有一种方法可以强制我的本地应用程序的命名路由优先?

6 个答案:

答案 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中定义的路由规则从上到下应用,直到找到匹配项。只需将优先级较高的规则移动到上安装引擎的行,我就可以覆盖已安装引擎中定义的路由。所以,

&#13;
&#13;
get 'about', controller: 'static', action: 'about', as: 'about'
mount My::Engine => '/'
&#13;
&#13;
&#13;

导致应用程序路由/关于/请求(在本例中)为静态控制器,而:

&#13;
&#13;
mount My::Engine => '/'
get 'about', controller: 'static', action: 'about', as: 'about'
&#13;
&#13;
&#13;

导致应用程序路由/ about / requests到已挂载引擎中定义的路由。