2012-04-05 12 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) 

私の上記の解決策は動作しますが、私はそれが物事の間違った方法だ疑いを持っています。 Rubyのベテランが私にこれを行うためのよりエレガントな方法を示すことができれば - そして/またはなぜ2番目の解決策が呼び出されないのか - 私は感謝しています。

+2

なぜ2番目の方法が機能しないのかについては、こちらをご覧ください:http://stackoverflow.com/questions/5944278/overriding-method-by-another-defined-in-module – tsherif

+0

これは多くの助けになりました。多くの感謝 – PlankTon

答えて

4

あなたがサルをパッチするときは、継承するスーパーがないので、メソッドを再定義する必要があります(2番目のコードの抜粋は使用できません)。

現在のメソッドの実装をコピーして、独自の追加だけでトラブルを求めているので、alias_methodの出番です。

alias_method :form_for_without_cherries, :form_for 

それは実際にあなたが代わりにを使用することができ、元の方法にクローンを作成し、スーパー。あなたがサルのパッチを連鎖させることができないという事実はバグではなく、それは機能です。

rails alias_method_chainメソッドは実際には推奨されていませんでしたが、それは最初から貧弱なアイデアだったからです。しかし、alias_methodは純粋なルビメソッドであり、正しく使用されると、猿のパッチ適用のエレガントな方法が提供されます。そのため、すぐにはいつでもすぐに外に出ることはありません。

+0

優秀 - バイスに感謝します。 – PlankTon

関連する問題