要扩展rails'`link_to`,我应该使用`alias_method_chain`还是mixins +继承?

时间:2012-11-26 13:01:24

标签: ruby-on-rails ruby metaprogramming

我正在使用twitter bootstrap创建应用。我正在使用Font Awesome向各个地方添加图标,通常是链接。到目前为止,我一直在使用全球帮手。这是简化版本:

# app/helpers/link_to_with_icon.rb
def link_to_with_icon(text, path, options={})
  options = options.clone
  icon = options.delete(:icon)
  text = "<i class='#{icon}'></i> #{text}" if icon.present?
  link_to(text, path, options)
end

这很有用,但每次我需要在新链接中添加图标时,我都必须记住将link_to更改为link_to_with_icon(该应用是新的,因此这种情况会不断变化)。所以我决定完全停止使用link_to,并将其替换为link_to_with_icon(因为它兼容)。

但后来我意识到,由于我不再使用link_to,我不妨首先修改link_to。当然,我可以在lib文件夹中添加一些monkeypatching,以使其理解:icon选项。

# lib/extensions/url_helper_extensions.rb
module ActionView
  module Helpers
    module UrlHelper

      # do some magic here

    end
  end
end
几年前,我做过类似的事情。在那段时间里,alias_method_chain助手是这项工作的正确工具。在rails 3.x中,它似乎是deprecated in favor of modules and inheritance

但是,如果我正确理解该页面中的示例,我需要某种link_to模块提供Base方法 - 否则您无法添加“延伸“到它。

因此我的问题:我可以使用模块扩展link_to吗?或者我必须使用alias_method_chain吗?

特别值得一提的是:icon选项的工作实现。

2 个答案:

答案 0 :(得分:3)

我只是这样做:

# app/helpers/my_helper.rb

module MyHelper
  def link_to(text, path, options={})
    options = options.clone
    icon = options.delete(:icon)
    text = "<i class='#{icon}'></i> #{text}" if icon.present?
    super(text, path, options)
  end
end

但请注意,如果您使用link_to阻止。

答案 1 :(得分:2)

我会将其添加到单独的帮助器中,或将其添加到ApplicationHelper

def link_to(text, path, options = {}, &block)
  icon = options.delete(:icon)
  text = content_tag(:i, text, :class => icon) if icon
  super
end

并且您不希望克隆选项哈希,因为您不希望将icon选项发送到原始link_to方法。