2009-06-04 9 views
1

私のコードをDRYしているので、特定のメソッドを別のオブジェクトに延期するかデリゲートするメソッドを作成しています。ここに基本的なアイデアがあります:私はReroute < AbstractShipmentを持つことができるShipment < AbstractShipmentを持っています。 ShipmentまたはRerouteのいずれかにDelivery(または配送先)を指定できますが、両方を指定することはできません。エイリアス化されたメソッドからスーパーを呼び出す

私がshipment.deliveriesを呼び出すと、最初にリルートがあるかどうかを確認したいと思います。そうでない場合は、AbstractShipmentdeliveriesメソッドを呼び出します。その場合は、メソッドをリルートに委譲します。

私は、以下の簡単なコードでこれを試してみました:

module Kernel 
    private 
    def this_method 
     caller[0] =~ /`([^']*)'/ and $1 
    end   
end 

class Shipment < AbstractShipment 
    ... 

    def deferToReroute 
    if self.reroute.present? 
     self.reroute.send(this_method) 
    else 
     super 
    end 
    end 

    alias_method :isComplete?, :deferToReroute 
    alias_method :quantityReceived, :deferToReroute 
    alias_method :receiptDate, :deferToReroute 
end 

Kernel.this_methodが呼び出された方法を見つけるための単なる便利です。しかし、superを呼び出すと、私は少しを検索し、これはRubyの1.8のバグですが、1.9に固定されていることを説明しthis linkを見つけ

super: no superclass method `deferToReroute' 

スローします。残念ながら、このコードを1.9にアップグレードすることはできません。回避策の提案は誰にもありますか?

編集:-)

ありがとう:は私のコードを見てのビットの後、私は実際に私が実際にのみ上書きするために必要な、私がやった方法の全てをエイリアスする必要がないことに気づきました他の3人は実際に計算のためにそれを呼び出すので、配送方法。しかし、私は以前にこれにぶつかって以来、私はまだy'allの考えを知りたいです。

答えて

2

よりもむしろここalias_methodを使用して、あなたはより良いハードオーバーライドし、これらの方法によって提供される可能性がありますので、同じよう:

class Shipment < AbstractShipment 
    def isComplete? 
    return super unless reroute 
    reroute.isComplete? 
    end 
end 

あなたはクラスごとに、この5〜10回行っている見つけた場合、あなたはそれを作ることができますよりよいそうのようにストレートにevalを使用して

class Shipment < AbstractShipment 
    def self.deferred_to_reroute(*method_names) 
    method_names.each do |method_name| 
     eval "def #{method_name}; return super unless reroute; reroute.#{method_name}; end" 
    end 
    end 
    deferred_to_reroute :isComplete?, :quantityReceived, :receiptDate 
end 

good performance characteristicsを提供していますし、あなたがあなたのクラス定義の中に何をしているかについての簡単な、宣言構文を持つことができます。

+0

恐ろしい!もし私がもう少し長く遊んでいたら、私はこれと似たようなプラグインを書いているので、このような試みをしただろうが、それはきれいだっただろう。どうもありがとう :-) –

関連する問題