覆盖 Rails 3 引擎提供的命名路由

发布于 2024-11-07 11:22:55 字数 661 浏览 1 评论 0原文

我正在开发一个使用 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"}

)强制本地应用程序的命名路由优先的好方法?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

秋意浓 2024-11-14 11:22:55

我通过将引擎的路由从 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

然后我可以愉快地用引擎中的路由覆盖基本应用程序中的任何路由。

请注意,覆盖路由需要在被覆盖路由之前定义,因为较早定义的路由优先于较晚定义的路由。

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.

意犹 2024-11-14 11:22:55

恐怕没有这么简单的方法。路由在 lib/action_dispatch/routing/mapper.rb:271 中定义,它调用 RouteSet 上的 add_route(在rack-mount-0.6.14/lib/rack/mount/ 中定义) route_set.rb,并在第 71 行附加了名称)。没有remove_route方法,引擎的路由是最后添加的。您可以在使用 Rails.application.routes.draw 初始化应用程序后手动添加路线,而不是将其放在 paths.rb 中,或者您可以修补引擎。

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.

那一片橙海, 2024-11-14 11:22:55

无法覆盖引擎内的路线。相反,您必须定义一条否决路线。您可以通过在引擎的路由器上调用 prepend 来完成此操作:

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

如果引擎的命名空间是隔离的,则这将使用引擎命名空间内部的 SomewhereController 。如果没有,它将使用典型的 SomewhereController

如果你想覆盖路由以返回 404,我能想到的最好方法是重定向到 404 页面:

match "/route_goes_here" => redirect("/404")

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")
请远离我 2024-11-14 11:22:55

您需要将初始值设定项挂钩添加到 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,您可以覆盖它们的路由。

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.

若沐 2024-11-14 11:22:55

您可以按照上面 Ryan Bigg 的建议预先添加路线。我发现为了用我的自定义路由推翻命名路由助手,我需要调用 append 而不是 prepend,如下所示:

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

否则应用程序包含路由和命名助手for 引擎的路由器是最后一个定义,因此也是应用的定义。

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.

我们的影子 2024-11-14 11:22:55

在routes.rb中定义的路由规则从上到下应用,直到找到匹配。我只需将较高优先级的规则移动到安装引擎的行上方即可覆盖已安装引擎中定义的路线。所以,

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

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

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

导致应用程序将 /about/ 请求路由到已安装引擎中定义的路由。

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.

忆离笙 2024-11-14 11:22:55

要替换 gem 或引擎提供的默认路由路径,我们可以通过以下方式实现。
对我来说,我想将所有路线中的“spree_user”替换为“account”等
/user/spree_user/sign_in 我按照以下方式执行此操作

步骤 1
创建 config/some_engine_route_override.rb
复制引擎路由文件的内容并根据需要更新路由

第2步
在 application.rb 中使用以下钩子

# Override Spree Core routes in order to translate products routes
initializer "delete_spree_core_routes", after: "add_routing_paths" do |app|
  new_spree_auth_route_path = File.expand_path('../../config/some_engine_route_override.rb', __FILE__)
  routes_paths = app.routes_reloader.paths

  spree_devise_auth_route_path = routes_paths.select{ |path| path.include?("spree_auth_devise") }.first

  if spree_devise_auth_route_path.present?
    spree_core_route_path_index = routes_paths.index(spree_devise_auth_route_path)

    routes_paths.delete_at(spree_core_route_path_index)
  
    routes_paths.insert(spree_core_route_path_index, new_spree_auth_route_path)
   
  end
end

To Replace the default routes path provided by gem or engine we can achive that in following way.
For me I wanted to replace 'spree_user' with 'account' etc from all routes
/user/spree_user/sign_in I did this in following way

Step 1
Create config/some_engine_route_override.rb
Copy the content of engine route file and update the routes as per need

Step 2
in application.rb use the folllowing hook

# Override Spree Core routes in order to translate products routes
initializer "delete_spree_core_routes", after: "add_routing_paths" do |app|
  new_spree_auth_route_path = File.expand_path('../../config/some_engine_route_override.rb', __FILE__)
  routes_paths = app.routes_reloader.paths

  spree_devise_auth_route_path = routes_paths.select{ |path| path.include?("spree_auth_devise") }.first

  if spree_devise_auth_route_path.present?
    spree_core_route_path_index = routes_paths.index(spree_devise_auth_route_path)

    routes_paths.delete_at(spree_core_route_path_index)
  
    routes_paths.insert(spree_core_route_path_index, new_spree_auth_route_path)
   
  end
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文