将额外的参数传递给Rails观察者

时间:2012-02-23 01:50:18

标签: ruby-on-rails observer-pattern

我在帐户模型中有几种方法:付款,接收,退款等我希望我的AccountObserver观看。但我想将额外的对象传递给我的AccountObserver。

例如,在我的帐户模型中,我想定义:

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

end

我该怎么做?

谢谢。

3 个答案:

答案 0 :(得分: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)

答案 1 :(得分: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

答案 2 :(得分: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的方法内部,就像上面的答案一样。