22

我想使用 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 patching:重新打开 rails helper 模块。如果 Rails 团队更改了他们的帮助模块的名称,我的代码就会变得脆弱。并非不可克服,但并不理想。
  2. 使用不同的方法名:试图坚持通用的 Rails 接口可能是我的失败。我的更改可能会引起其他开发人员的困惑
  3. 分离方法(新):不确定这是否可行,或者它是否具有与 1 相同的缺点。将对此进行研究,但这可能是一个很好的起点。

所以这里的问题是,我是坚持使用这些次优解决方案之一,还是有另一种我没有考虑过的方法?如果我选择选项 3,有没有办法在不直接解决 rails helper 模块的情况下做到这一点?

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

4

4 回答 4

38

有比您列出的任何选项更好的方法。只需使用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 核心团队在您身上转移东西!

于 2012-05-09T22:54:37.680 回答
5

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

假设您想记录对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

于 2012-05-06T15:45:20.043 回答
5

尝试使用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
于 2012-05-14T16:20:20.320 回答
2

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

应该调用您的新方法awesome_stylesheet_link_tag,以便其他 Rails 开发人员可以阅读您的代码并提出问题“链接标签有什么了不起的地方?”。

作为一个较小的更改,您可以进行覆盖,但:awesome => true作为参数传入,这样他们至少有一个线索表明正在发生一些事情。

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

于 2012-05-14T02:39:10.357 回答