alias_method,alias_method_chain和self.included

时间:2012-04-05 17:08:47

标签: ruby-on-rails ruby alias-method alias-method-chain

我对alias_method / alias_method_chain的理解有点困难。我有以下代码:

module ActionView::Helpers
  module FormHelper

    alias_method :form_for_without_cherries, :form_for

    def form_for(record, options = {}, &proc)
      output = 'with a cherry on top'.html_safe
      output.safe_concat form_for_without_cherries(record, options = {}, &proc)
    end
  end
end

这正是我想要的 - 在任何form_for电话的顶部追加“顶部有一个樱桃”。

但我的理解是,由于一些原因,这不是好的代码。首先,它不会链接到form_for(?)的任何其他覆盖,所以如果我要编写第二个form_for方法,其中附加“而另一个樱桃在顶部”,它将不会显示。其次,alias_methodalias_method_chain是过时的解决方案,我应该使用self.included&而是发送到模块。

但我无法让self.included调用此form_for方法 - 它只是一直调用父方法。这是我正在尝试的:

module CherryForm
  def self.included(base)
    base.extend(self)
  end

  def form_for(record, options = {}, &proc)
    output = 'with a cherry on top'.html_safe
    output.safe_concat super(record, options = {}, &proc)
  end 
end

ActionView::Helpers::FormHelper.send(:include, CherryForm)

我的上述解决方案有效,但我怀疑这是错误的做事方式。如果任何红宝石老兵能够向我展示一种更优雅的方式 - 和/或为什么没有调用第二种解决方案 - 我会很感激。

1 个答案:

答案 0 :(得分:4)

当你修补某些东西时,你必须重新定义该方法,因为没有超级继承(所以你不能使用第二个代码摘录)。

复制当前的方法实现并添加自己的方法只会遇到麻烦,所以这就是alias_method的用武之地。

alias_method :form_for_without_cherries, :form_for

它实际上为原始方法创建了一个克隆,您可以使用它而不是super。你无法链接猴子补丁的事实不是一个错误,它是一个功能。

rails alias_method_chain方法确实已被弃用,但这只是因为从一开始就是一个糟糕的主意。然而alias_method是一种纯粹的ruby方法,如果使用正确可以提供一种优雅的猴子修补代码方式,这就是为什么我很确定它不会很快消失。