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

use*_*769 22 ruby overriding ruby-on-rails 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
Run Code Online (Sandbox Code Playgroud)

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

  1. 猴子修补:重新打开rails helper模块.如果rails团队改变了他们的帮助器模块的名称,我的代码就变成了脆弱的来源.不是不可克服的,但并不理想.
  2. 使用不同的方法名称:试图坚持共轨接口可能是我的垮台.我的更改可能会成为其他开发人员混淆的根源
  3. 分离方法(新):不确定这是否有效,或者它是否会有与1相同的缺点.研究这个,但这可能是一个很好的起点.

所以这里的问题是,我是否坚持使用其中一种次优解决方案,还是有其他方式我没有考虑过?如果我选择选项3,有没有办法在不直接寻址rails helper模块的情况下执行此操作?

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

Cad*_*ade 34

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

module AwesomeHelper
  def stylesheet_link_tag(*sources)
    if @be_awesome
      awesome_stylesheet_link_tag *sources
    else
      super
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

覆盖stylesheet_link_tagAwesomeHelper将确保在stylesheet_link_tag被调用时,Ruby会在方法查找路径中遇到它ActionView::Helpers::AssetTagHelper.如果@be_awesometrue,你可以在那里负责并停止,如果没有,那么super没有括号的调用将透明地传递到Rails实现的所有参数.这样你就不用担心Rails核心团队会在你身上移动东西!

  • @jdoe是的,你是对的.为了使用一个代码,需要包含它.:)我不认为这是一个"陷阱".在`ApplicationController`中使用[AbstractController :: Helpers :: ClassMethods :: helper](http://api.rubyonrails.org/classes/AbstractController/Helpers/ClassMethods.html#method-i-helper)可能有助于减轻您的顾虑. (2认同)

jdo*_*doe 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
Run Code Online (Sandbox Code Playgroud)

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


gmi*_*ile 6

尝试使用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
Run Code Online (Sandbox Code Playgroud)