Simple way of turning off observers during rake task?

Viewed 11839

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 Answers

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

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.

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

Model.delete_observers

You can take the method off the observer;

MessageObserver.send(:remove_method, :after_create)

Will stop the :after_create on MessageObserver by removing it.

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

There isn't a straightforward way to disable observers that I know of, but it sounds possible to add logic to your observer to not send an email when the activation code is set...

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
Related