通过访问原始文件覆盖rails帮助程序

时间:2012-05-06 15:01:40

标签: ruby-on-rails ruby override helpers

我想使用rails熟悉的助手,但功能略有改变。我看待它的方式,我希望能够做到这样的事情:

module AwesomeHelper
  #... create alias of stylesheet_link_tag to old_stylesheet_link_tag
  def stylesheet_link_tag(*args)
    if @be_awesome
      awesome_stylesheet_link_tag *args
    else
      old_stylesheet_link_tag *args
    end
  end
end

我看到它的方式,我有三个选择:

  1. Monkey修补:重新打开rails helper模块。如果rails团队改变了他们的帮助器模块的名称,我的代码就变成了脆弱的来源。不是不可克服的,但并不理想。
  2. 使用不同的方法名称:试图坚持使用共轨接口可能是我的垮台。我的更改可能会成为其他开发人员混淆的原因
  3. 分离方法(新):不确定这是否有效,或者它是否会有与1相同的缺点。请研究一下,但这可能是一个很好的起点。
  4. 所以这里的问题是,我是否坚持使用其中一种次优解决方案,还是有其他方式我没有考虑过?如果我选择选项3,有没有办法在不直接寻址rails helper模块的情况下完成它?

    (注意:我删除了上下文,因为它没有对问题添加任何内容。)

4 个答案:

答案 0 :(得分:33)

有比你列出的任何选项更好的方法。只需使用super

module AwesomeHelper
  def stylesheet_link_tag(*sources)
    if @be_awesome
      awesome_stylesheet_link_tag *sources
    else
      super
    end
  end
end

在AwesomeHelper中覆盖stylesheet_link_tag将确保在调用stylesheet_link_tag时,Ruby会在方法查找路径中遇到它,然后才能到达ActionView::Helpers::AssetTagHelper。如果@be_awesometrue,您可以在那里负责并停止操作,如果没有,则在没有括号的情况下调用super将透明地传递所有参数直到Rails实现。通过这种方式,您无需担心Rails核心团队会在您身上移动事物!

答案 1 :(得分:6)

我不使用这个宝石,所以我会以更通用的方式回答你。

假设你要记录对link_to助手的调用(是的,人为的例子,但显示了这个想法)。查看API可让您了解位于link_to模块中的ActionView::Helpers::UrlHelper。因此,您可以在您的config/initializers目录中创建一些文件,其中包含以下内容:

# like in config/initializers/link_to_log.rb
module ActionView::Helpers::UrlHelper

    def link_to_with_log(*args, &block)
        logger.info '**** LINK_TO CALL ***'
        link_to_without_log(*args, &block) # calling the original helper
    end

    alias_method_chain :link_to, :log
end

此功能的核心 - alias_method_chain(可点击)。在定义方法xxx_with_feature之后使用它。

答案 2 :(得分:4)

尝试使用alias_method

module AwesomeHelper
  alias_method :original_stylesheet_link_tag, :stylesheet_link_tag

  def stylesheet_link_tag(*sources)
    if @be_awesome
      awesome_stylesheet_link_tag *sources
    else
      original_stylesheet_link_tag *sources
    end
  end
end

答案 3 :(得分:2)

我真的鼓励你考虑你的选项#2,以一种对调用者来说显而易见的方式覆盖rails方法的行为。

您的新方法应该被称为awesome_stylesheet_link_tag,以便其他Rails开发人员可以读取您的代码并询问“链接标记有什么特别之处?”。

作为一个较小的更改,您可以执行覆盖,但传递:awesome => true作为参数,因此他们至少知道某些事情正在发生。

更改广泛使用的方法(如stylesheet_link_tag)的行为会在不需要的地方产生潜在的未来误解。