如何全局覆盖rails url helper?

我需要添加一个简单的更改到foo_path ,所以我这样做:

module ApplicationHelper # [...] def foo_path(foo, options = {}) options.merge!(bar: foo.some_attribute) super end # [...] end 

现在,这在从视图调用时起作用,但是当从控制器调用时,使用没有添加的原始变体。

如何覆盖应用程序范围内的相应帮助程序(_path / _url)?

我认为最简单的方法是自定义routes.rb文件(至少对于静态默认参数)。 文档: http : //guides.rubyonrails.org/routing.html#customizing-resourceful-routes

默认参数示例

 get "/foo(/:bar)" => "my_controller#index", defaults: { bar: "my_default" } 

默认参数值示例+范围

 scope '/(:rec_type)', defaults: { rec_type: 'mammo' }, rec_type: /mammo|face/ do resources :patients end 

其他选项(用于动态限制):

高级路由约束:

如果您需要更高级/动态限制,请查看本指南: http : //guides.rubyonrails.org/routing.html#advanced-constraints 。

覆盖default_url_options:

此外,您可以覆盖default_url_options方法,以使用路径助手自动添加一些属性(参数): http : //guides.rubyonrails.org/action_controller_overview.html#default-url-options 。

您可以通过在控制器中定义名为default_url_options的方法来设置URL生成的全局默认参数。 这样的方法必须返回具有所需默认值的哈希值,其键必须是符号:

 class ApplicationController < ActionController::Base def default_url_options(options = {}) if action_name == 'foo' # or other conditions options[:bar] = 'your_defaults' # add here your default attributes end options end end 

覆盖to_param:

Rails路由系统在模型上调用to_param以获取:id占位符的值。 ActiveRecord::Base#to_param返回模型的id,但您可以在模型中重新定义该方法。 例如,给定:

 class Product < ActiveRecord::Base def to_param "#{id}-#{title}" end end 

这会产生: /products/254-Foo

看起来你面临着错误的方式。 您最好在路线中添加:bar param,例如:

 get :foo, :bar => "bar" 

否则,请提供有关您的问题的更多描述性详细信息。

编辑。

这是解决方案(基本在您的更新后):

 class ApplicationController < ActionController::Base def foo_path(foo, options = {}) options.merge!(bar: foo.some_attribute) super end helper_method :foo_path end 

在Rails 3和4中,路由url帮助程序都驻留在此模块Rails.application.routes.url_helpers 。 所以我们可以包含一个模块来覆盖其中的方法。

 module FooUrlHelper def foo_path(foo, options = {}) options.merge!(bar: foo.some_attribute) super end end # Works at Rails 4.2.1 Rails.application.routes.url_helpers.send(:include, FooUrlHelper) # For Rails 4.2.6, I thought the following worked, but there seems to be issues, don't have time to figure out a solution yet Rails.application.routes.named_routes.url_helpers_module.send(:include, FooUrlHelper) 

你可以把它放在初始化器中

我在控制台和控制器中尝试了这个,似乎工作正常。

正如当前的答案所示,您没有覆盖rails帮助程序(在app/helpers文件夹中的某个位置定义),而是覆盖路由帮助程序(在config/routes.rb定义)。

从视图中调用方法foo_path是有效的,因为在查看可用的路由助手方法之前,第一个Rails将查看所有可用的应用程序助手方法。

从控制器调用该方法不起作用,因为Rails只会通过可用的路由助手方法,而不是通过路由助手。

如果要从控制器调用应用程序助手,请在控制器中使用:

 view_context.foo_path(...) 

这需要您添加view_context. 对于每个控制器内每次调用foo_path ,所以它不是一个完美的解决方案,但它应该工作。