Simple way of turning off observers during rake ta

2019-01-13 12:53发布

I'm using restful_authentication in my app. I'm creating a set of default users using a rake task, but every time I run the task an activation email is sent out because of the observer associated with my user model. I'm setting the activation fields when I create the users, so no activation is necessary.

Anyone know of an easy way to bypass observers while running a rake task so that no emails get sent out when I save the user?

Thanks.

12条回答
叛逆
2楼-- · 2019-01-13 13:13

In generally, for these sorts of situations, you can:

  1. Set up a mock object to "absorb" the unwanted behavior
  2. Have an externally accessible flag / switch that the observers respect to inhibit the behavior
  3. Add logic to the observer to detect when the behavior is unneeded in general (e.g. what dbarker suggests)
  4. Have a global flag "testing", "debug", "startup" or whatever that changes low level behavior
  5. Introspect and remove the observers
  6. Add a method to your model that performs an alternative, unobserved version of the task (sharing implementation with the normal method as much as possible).

In this case, I'd say #3 is your best bet.

查看更多
孤傲高冷的网名
3楼-- · 2019-01-13 13:13

I came here looking for the an answer to the same... none of the above seemed to do the trick (or involve adding migration-specific logic to my application code -- boo).

Here's what I came up with (a bit lame that it needs to go in each relevant migration, but...)

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
查看更多
ゆ 、 Hurt°
4楼-- · 2019-01-13 13:16

Rails 3.1 finally comes with API for this: 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

Where ORM could for example be ActiveRecord::Base

查看更多
Viruses.
5楼-- · 2019-01-13 13:25

When running tests on an app I am working on, I use the following:

Model.delete_observers
查看更多
Animai°情兽
6楼-- · 2019-01-13 13:26

You could add an accessor to your user model, something like "skip_activation" that wouldn't need to be saved, but would persist through the session, and then check the flag in the observer. Something like

class User
  attr_accessor :skip_activation
  #whatever
end

Then, in the observer:

def after_save(user)
  return if user.skip_activation
  #rest of stuff to send email
end
查看更多
Melony?
7楼-- · 2019-01-13 13:26

As others have hinted; I would wrap the unwanted logic in your Observer with a simple if statement.

def after_create
  send_email if RAILS_ENV == "production"
end
查看更多
登录 后发表回答