2012-04-05 44 views
3

我在理解alias_method/alias_method_chain时有点困难。我有以下代码:alias_method,alias_method_chain和self.included

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) 

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

+2

至于为什么第二种方法不起作用,请参阅:http://stackoverflow.com/questions/5944278/overriding-method-by-another-defined-in-module – tsherif 2012-04-05 17:38:55

+0

这有助于很多。非常感谢 – PlankTon 2012-04-05 18:10:36

回答

4

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

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

alias_method :form_for_without_cherries, :form_for 

它实际上创建了一个克隆原来的方法,你可以用它来代替超。事实上,你不能链猴子补丁不是一个错误,这是一个功能。

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

+0

非常好 - 谢谢vise。 – PlankTon 2012-04-05 21:52:20