2012-02-23 16 views
4

アカウントモデルには、AccountObserverに見せたい支払い、受け取り、払い戻しなどのいくつかのメソッドがあります。しかし私は、私のAccountObserverに余分なオブジェクトを渡したいと思います。Railsオブザーバーに余分な引数を渡す

例えば、私のアカウントモデルでは、私が定義したいと思います:

def pay 
    ... 
    notify_observers(:after_pay, payee, amount) 

end 

は、私はこれをどのようにしたらよいでしょうか?

ありがとうございます。

+0

私が気にする最も自然なことは、監視対象のオブジェクトが関連するアカウント、受取人、金額にアクセスできるようになるため、代わりに「支払い」または「取引」モデルを使用し、過去の取引のためにペーパートレイルを持っているという追加のボーナスがあります。 –

+0

ありがとう、ヨルダン。あなたの提案は非常に洞察力がありますが、私はプログラミングロジックに関係しない理由でこの状況でその決定を変更することはできません:) – AdamNYC

答えて

2

これは、オブザーバーにとっては非常に良いユースケースではないと思います。私は全く別のルートを行くことなく、あなたが観察者にアクセスすることができ、あなたのAccountオブジェクトのインスタンス変数を設定することで、考えることができます最善の方法、例えば:

class Account < ActiveRecord::Base 
    attr_reader :last_payment 

    def pay payee, amt 
    @last_payment = [ payee, amt ] 

    notify_observers :after_pay 
    end 
end 

class AccountObserver < ActiveRecord::Observer 
    def after_pay account 
    payee, amt = account.last_payment 

    Rails.logger.info "#{payee} paid #{amt}!" 
    end 
end 
+0

ありがとう、ヨルダン。私はソースコードを見て、私が望むことをするためにnotify_observersをオーバーライドしなければならないことに気付きました。 – AdamNYC

7

notify_observersを上書きしないでください。コアクラスにパッチを当てることは本当に悪い考えです。代わりに、何をやるべきことはこれです:

だけではなく、メソッド名に制限されているモデルのinstance methodを呼び出して、クラスのメソッドを自分で呼び出す:

# Notify list of observers of a change. 
def notify_observers(*arg) 
    observer_instances.each { |observer| observer.update(*arg) } 
end 

それはあなたが与える任意の引数に沿って通過しますあなたのオブザーバーの#updateメソッドに渡します。これは、自分のオブザーバークラスの中に上書きすることができます。

デフォルトは余分な引数を受け入れないが、あまりにも複雑ではありませんん。

def update(observed_method, object, &block) #:nodoc: 
    return unless respond_to?(observed_method) 
    return if disabled_for?(object) 
    send(observed_method, object, &block) 
end 

だから、単に例えば、あなたの観察者にこれを追加します。

def update(observed_method, object, *args) 
    return unless respond_to?(observed_method) 
    return if disabled_for?(object) 
    send(observed_method, object, *args) 
end 

def after_pay(payee, amount) 
    ... 
end 

とコール

Payee.notify_observers(:after_pay, payee, amount) 
+0

これは素晴らしいです、FX!どうもありがとう。 – AdamNYC

+0

ありがとう!私はクラスレベルの 'notify_observers'を自分で呼び出す必要があることを理解しましたが、それでも動作させることはできませんでした。これは、私自身がオブザーバ自体に対して 'update'インスタンスメソッドを修正する必要があることを知りました。 –

1

遅れて回答しましたが、誰かが参考になることを願っています。

まず第一に、それはbeing fixed in Rails 4

ようだが、私のRails 3プロジェクトは、私はクラスレベルnotify_observersコールにハッシュを渡しています。

self.class.notify_observers :organisation_added_to_group, { group: self, organisation: organisation } 

、観察者には、私はこのハッシュを受けています:

def organisation_added_to_group(args) 
    puts args[:group] 
    puts args[:organisation] 
end 

私は上記の回答のように、updateのメソッドの内部を気にしないことを好みます。

関連する問題