2009-06-16 3 views
0

私はオンラインストアを開発しており、顧客は注文を削除して商品を自動的に補充する必要があります(テストオーダーなど)。エイリアス処理の方法はなんですか?

class Order < ActiveRecord::Base 
    def destroy_and_restock 
    restock_products 
    destroy 
    end 

    protected 

    def restock_products 
    line_items.each do |li|  
     li.product.quantity_on_hand += li.quantity 
     li.product.save 
    end 
    end 
end 

しかし、別のdestroy_and_xメソッドを後で作成する必要がある場合はどうすればよいですか。 Xをパラメータとしてdestroy()メソッドに渡すことを許可しないでください。だから今、私はこれで行こうと思っています:

alias :old_destroy :destroy 
def destroy(options = {}) 
    if options['restock'] == true 
    restock_products 
    end 
    old_destroy 
end 

protected 

def restock_products 
    line_items.each do |li|  
    li.product.quantity_on_hand += li.quantity 
    li.product.save 
    end 

これは、より拡張性ですが、私はやや汚い感じさせます。私は汚い感じに間違っていますか?これを行うより良い方法はありますか?

+1

Xとは何ですか?それは意味をなさない。何個のXがあるのでしょうか? 拡張性以外の理由で「拡張可能」にすることに巻き込まれないようにしてください。 – whatsisname

+0

必要なときに拡張性を心配します。実際のケースがあるまでは、何を拡張するのかを知ることは難しいです。 –

+0

Xは "払い戻し"に等しいかもしれません、(@ order.destroy_and_refundのように) –

答えて

2

「はい、これは汚れています」と言います。あなたの意図は、 'destroy'メソッドの動作を変更するのではなく、ドメイン固有の作業を行うことです。destroyを実行してください。あなたの最初のアプローチは素晴らしいです - あなたが望むことをするメソッドを定義し、必要に応じてdestroyを呼び出します。あなたが考えているように、メソッドを 'ラッピング'や 'モンキーパッチング'する方法は、標準的なオブジェクト指向のアプローチを使用できないときに最適な手法です - たとえば、あなたのコントロールの範囲外で定義され使用されるクラス。あなたdestroy方法自体の動作を変更を検討している場合であっても

、私はむしろそれを包むよりも、ここでメソッドをオーバーライドをお勧めしたい:

def destroy(options = {}) 
    restock_products if options['restock'] 
    super() # I think parens are necessary here, to avoid passing options up the chain 
end 
+0

まず、「汚い」方法の実装は明らかに私のものよりはるかに優れています。第二に、私は私の "意図は、"破壊 "メソッドの動作を変更しないことです - 私は"本当に "破壊メソッドにパラメータを取ろうとしていませんか? –

+0

私が追加されます:あなたは破壊が呼び出されたときに何かが常に起こっていることを確認したいと思った場合はメソッドをオーバーライドすることは、より適切であろう - それでもエイリアシングを必要としないこと。あなたが/エイリアシングオーバーライドするべきではありません手掛かり:それはあなたのために「破棄」呼び出したときに、「オプション」のオプションパラメータは、ここでActiveRecordのフレームワークによって渡されることはありませんでしょう。知識のある呼び出し元だけがオプションを渡す方法を知っているので、代わりに別のメソッドを使用することを同等に知っていました。 – joshng

+0

私たちのコメントは重複していますので、私は今あなたに返信します:-)。いいえ、私はあなたが本当に「破壊」の行動を修正したいとは思わないと思います。既存の '破棄'動作を含む新しい動作を追加したいと思っています。 は考えてみましょう:あなたは、極端にあなたのアイデアを取り、ちょうどクラスにすべてを行い一つの方法を書くことができる(たとえば、それを呼び出す...「送信」;-)。次に、「オプション」に基づいて切り替えて、何をすべきかを決定します。 – joshng

0

どのようにだけブロックを使用してはどうですか?そして、あなたはクラスでこれを設計しながら、離れてあなたの髪を引っ張って持っていけない、あなたは、よりを行うことができますし、必要なときには:

def destroy_after &block 
    yield if block 
    destroy 
end 

次に、このようにそれを呼び出す:

order.destroy_after { order.restock_products } 

を私がすることはできませんこの機能の良い名前を考えてみてください...しかし、私はあなたがそのアイデアを得ることを願っています。

+0

ここでの問題点の1つは、destroy()のコンテキストの外でrestock_products()を使用する理由が考えられないため、restock_products()を保護するあなたの解決策とは関係ありません)。 –

+0

私はこのアプローチが達成するものを見ません...あなたはブロックを外で実行し、破壊を呼び出してもよいでしょう: order.restock_products order.destroy – joshng

+0

err ...フォーマットが失われました。 order.restock_products; order.destroy – joshng

0

Horace、私はあなたの質問に誤解しました。私はあなたがこのために探していると思う:

http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

今、あなたはあなたの方法で保護され続けると、あなたが好きなだけbefore_destroyのものを追加することができます。破壊を無効にすることなく、これがあなたのために働くことを望みます。

幸運のベスト。

0

夜間に猿のパッチを当てても眠れない場合は、サブクラス化することで同じことができます。私が素早くハックする、または素早くデバッグするハックを必要とする時、私はサルのパッチも同様にします。

関連する問題