如何全局覆盖rails url helper?

use*_*825 7 ruby-on-rails

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

module ApplicationHelper
  # [...]

  def foo_path(foo, options = {})
    options.merge!(bar: foo.some_attribute)
    super
  end

  # [...]
end
Run Code Online (Sandbox Code Playgroud)

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

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

mar*_*ets 11

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

默认参数示例:

get "/foo(/:bar)" => "my_controller#index", defaults: { bar: "my_default" }
Run Code Online (Sandbox Code Playgroud)

默认参数值示例+范围:

scope '/(:rec_type)', defaults: { rec_type: 'mammo' }, rec_type: /mammo|face/ do
  resources :patients
end
Run Code Online (Sandbox Code Playgroud)

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

高级路由约束:

如果您需要更高级/动态限制,请查看本指南: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
Run Code Online (Sandbox Code Playgroud)

覆盖to_param:

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

class Product < ActiveRecord::Base
  def to_param
    "#{id}-#{title}"
  end
end
Run Code Online (Sandbox Code Playgroud)

这会产生: /products/254-Foo


lul*_*ala 5

在 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)
Run Code Online (Sandbox Code Playgroud)

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

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


int*_*ale 3

看来你面朝错误的方向。您最好在路线中添加 :bar 参数,例如:

get :foo, :bar => "bar"
Run Code Online (Sandbox Code Playgroud)

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

编辑。

这是解决方案(基于您的帖子更新):

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