I have several methods in Account model: pay, receive, refund etc. that I want my AccountObserver to watch. But I would like to pass extra objects to my AccountObserver.
For example, in my Account model, I would like to define:
def pay
...
notify_observers(:after_pay, payee, amount)
end
How should I do this?
Thank you.
Don't overwrite notify_observers. Patching core classes is a really bad idea. Instead, what you should do is this:
Instead of calling the instance method on your model which is restricted to just the method name, call the class method yourself:
# Notify list of observers of a change.
def notify_observers(*arg)
observer_instances.each { |observer| observer.update(*arg) }
end
It passes along any arguments you give it to the #update method of your observer, which you can overwrite inside your own observer class.
The default doesn't accept any extraneous arguments, but isn't too complex:
def update(observed_method, object, &block) #:nodoc:
return unless respond_to?(observed_method)
return if disabled_for?(object)
send(observed_method, object, &block)
end
So simply add this to your observer, for example:
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
And call
Payee.notify_observers(:after_pay, payee, amount)
I'm afraid that this isn't a very good use case for observers. The best way I can think of, without going a different route entirely, is to set a instance variables on your Account object which you can then access in the observer, e.g.:
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
Late response, but I hope somebody will find it helpful.
First of all, it seems being fixed in Rails 4
But in my Rails 3 project I'm passing a hash to class-level notify_observers
call.
self.class.notify_observers :organisation_added_to_group, { group: self, organisation: organisation }
And in the observer I'm receiving this hash:
def organisation_added_to_group(args)
puts args[:group]
puts args[:organisation]
end
I like that I don't care about update
's method internals, like in the answer above.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With