Передача дополнительных аргументов наблюдателю Rails - PullRequest
4 голосов
/ 23 февраля 2012

У меня есть несколько методов в модели учетной записи: оплата, получение, возврат средств и т. Д., Которые я хочу, чтобы мой AccountObserver наблюдал. Но я бы хотел передать дополнительные объекты моему AccountObserver.

Например, в моей модели Аккаунта я хотел бы определить:

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

end

Как мне это сделать?

Спасибо.

Ответы [ 3 ]

7 голосов
/ 12 мая 2012

Не перезаписывать notify_observers. Патчить базовые классы - это действительно плохая идея. Вместо этого вам следует сделать следующее:

Вместо вызова экземпляра метода в вашей модели, который ограничен только именем метода, вызовите метод класса самостоятельно:

# 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)
2 голосов
/ 23 февраля 2012

Боюсь, что это не очень хороший вариант использования для наблюдателей. Наилучший способ, который я могу придумать, не переходя полностью на другой маршрут, - это установить переменные экземпляра в вашем объекте 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
1 голос
/ 26 декабря 2013

Поздний ответ, но я надеюсь, что кто-то найдет его полезным.

Прежде всего, похоже, что исправлено в 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, как в ответе выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...