Простой способ отключить наблюдателей во время граблей? - PullRequest
39 голосов
/ 02 апреля 2009

Я использую restful_authentication в моем приложении. Я создаю набор пользователей по умолчанию, используя задачу rake, но каждый раз, когда я запускаю задачу, отправляется электронное письмо активации из-за наблюдателя, связанного с моей моделью пользователя. Я устанавливаю поля активации при создании пользователей, поэтому активация не требуется.

Кто-нибудь знает простой способ обойти наблюдателей во время выполнения граблей, чтобы при сохранении пользователя не отправлялись электронные письма?

Спасибо.

Ответы [ 12 ]

120 голосов
/ 02 декабря 2011

Rails 3.1 наконец-то поставляется с API для этого: http://api.rubyonrails.org/v3.1.0/classes/ActiveModel/ObserverArray.html#method-i-disable

ORM.observers.disable :user_observer
  # => disables the UserObserver

User.observers.disable AuditTrail
  # => disables the AuditTrail observer for User notifications.
  #    Other models will still notify the AuditTrail observer.

ORM.observers.disable :observer_1, :observer_2
  # => disables Observer1 and Observer2 for all models.

ORM.observers.disable :all
  # => disables all observers for all models.

User.observers.disable :all do
  # all user observers are disabled for
  # just the duration of the block
end

Где ORM может быть, например, ActiveRecord::Base

8 голосов
/ 10 марта 2011

В качестве флага для наблюдателя мне нравится определять метод доступа к классу с именем «disabled», поэтому он выглядит так:

class ActivityObserver < ActiveRecord::Observer
  observe :user

  # used in tests to disable the observer on demand.
  cattr_accessor(:disabled)
end

Я поставил это как условие в чувствительных обратных вызовах

def after_create(record)
       return if ActivityObserver.disabled
       # do_something
end

и я просто включаю флаг при необходимости

ActivityObserver.disabled=true
8 голосов
/ 03 апреля 2009

Вы можете добавить средство доступа к вашей пользовательской модели, что-то вроде «skip_activation», которое не нужно сохранять, но будет сохраняться в течение сеанса, а затем проверять флаг в наблюдателе. Что-то вроде

class User
  attr_accessor :skip_activation
  #whatever
end

Тогда в наблюдателе:

def after_save(user)
  return if user.skip_activation
  #rest of stuff to send email
end
6 голосов
/ 05 декабря 2010

Еще один, который вы можете попробовать (рельсы 3)

config.active_record.observers = :my_model_observer unless File.basename($0) == 'rake'
2 голосов
/ 05 октября 2010

Отключить наблюдателей для Rails 3 очень просто:

Rails.configuration.active_record.observers = []
2 голосов
/ 03 апреля 2009

При запуске тестов в приложении, над которым я работаю, я использую следующее:

Model.delete_observers
2 голосов
/ 02 апреля 2009

Как правило, для таких ситуаций вы можете:

  1. Настройка фиктивного объекта для "поглощения" нежелательного поведения
  2. Наличие доступного извне флага / переключателя, которые, по мнению наблюдателей, препятствуют поведению
  3. Добавить логику к наблюдателю, чтобы определить, когда поведение не требуется в целом (например, что предлагает dbarker)
  4. Иметь глобальный флаг "testing", "debug", "startup" или любой другой, который изменяет поведение низкого уровня
  5. Самоанализ и удаление наблюдателей
  6. Добавьте метод в вашу модель, который выполняет альтернативную ненаблюдаемую версию задачи (максимально разделяя реализацию с обычным методом).

В этом случае я бы сказал, что №3 - ваш лучший выбор.

1 голос
/ 13 декабря 2012
User.skip_callback("create", :after, :send_confirmation_email)

....

User.set_callback("create", :after, :send_confirmation_email)

Подробнее об этом:

Отключение обратных вызовов в Rails 3

1 голос
/ 31 января 2011

Я пришел сюда в поисках ответа на тот же вопрос ... ни одно из вышеперечисленного, похоже, не помогло (или не включило добавление логики, специфичной для миграции, в мой код приложения - boo).

Вот то, что я придумал (немного отстойно, что это нужно делать при каждой соответствующей миграции, но ...)

class ChangeSomething < ActiveRecord::Migration

  # redefine...
  class MessageObserver < ActiveRecord::Observer
    def after_create(observed) ; end
    def after_update(observed) ; end
  end

  def self.up
    # Message create/update stuff...
  end
end
1 голос
/ 11 февраля 2010

Вы можете снять метод с наблюдателя;

MessageObserver.send(:remove_method, :after_create)

Остановит: after_create на MessageObserver, удалив его.

...