Простой способ отключить наблюдателей во время рейк-задачи?

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

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

Спасибо.

Ответ 1

Вы можете добавить аксессуар в свою модель пользователя, что-то вроде "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

Ответ 2

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

Ответ 3

В качестве флага для наблюдателя мне нравится определять аксессуар класса, называемый "отключенным", поэтому он читается следующим образом:

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

Ответ 4

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

config.active_record.observers = :my_model_observer unless File.basename($0) == 'rake'

Ответ 5

В общем, для таких ситуаций вы можете:

  • Настройте макет объекта, чтобы "поглотить" нежелательное поведение.
  • Имейте внешний доступный флаг/переключатель, который наблюдатели соблюдают, чтобы запретить поведение.
  • Добавить логику наблюдателю, чтобы обнаружить, когда поведение вообще не требуется (например, что предлагает dbarker)
  • Имейте глобальный флаг "тестирование", "отладка", "запуск" или что-то другое, изменяющее поведение на низком уровне.
  • Взгляд и удаление наблюдателей
  • Добавьте метод к вашей модели, который выполняет альтернативную, ненаблюдаемую версию задачи (насколько возможно, совместное использование реализации с обычным методом).

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

Ответ 6

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

Model.delete_observers

Ответ 7

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

Rails.configuration.active_record.observers = []

Ответ 8

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

MessageObserver.send(:remove_method, :after_create)

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

Ответ 9

Я пришел сюда, чтобы найти ответ на тот же... Ни один из вышеперечисленных, похоже, не сделал этого трюка (или подразумевал добавление специфичной для миграции логики к моему коду приложения - 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

Ответ 11

Существует нет простого способа отключить наблюдателей, о которых я знаю, но кажется возможным добавить логику вашему наблюдателю, чтобы не отправлять электронное письмо, когда установлен код активации...

Ответ 12

Как намекают другие; Я бы обернул ненужную логику в Observer с помощью простого оператора if.

def after_create
  send_email if RAILS_ENV == "production"
end