38

Estoy usando restful_authentication en mi aplicación. Estoy creando un conjunto de usuarios predeterminados usando una tarea de rake, pero cada vez que ejecuto la tarea se envía un correo electrónico de activación debido al observador asociado con mi modelo de usuario. Estoy configurando los campos de activación cuando creo los usuarios, por lo que no es necesaria su activación.¿Manera simple de apagar observadores durante la tarea de rake?

Alguien sabe de una manera fácil de pasar por alto los observadores durante la ejecución de una tarea rastrillo de manera que no hay correos electrónicos se envían al guardar el usuario?

Gracias.

Respuesta

7

Se podría añadir un descriptor de acceso a su modelo de usuario, algo así como "skip_activation" que no necesitaría ser salvado, sino que persistir a lo largo de la sesión, y después comprobar la bandera en el observador. Algo así como

class User 
    attr_accessor :skip_activation 
    #whatever 
end 

Luego, en el observador:

def after_save(user) 
    return if user.skip_activation 
    #rest of stuff to send email 
end 
0

No hay una forma sencilla de desactivar los observadores, que yo sepa, pero suena posible añadir lógica a su observador para no enviar un correo electrónico cuando se establece el código de activación ...

2

En general, para este tipo de situaciones, se puede:

  1. Establecer un objeto de burla para "absorber" el comportamiento no deseado
  2. Tener una bandera/interruptor accesible desde el exterior que los observadores respecto a inhibir el comportamiento
  3. Añadir la lógica para que el observador detecte ct cuando el comportamiento se innecesarios en general (por ejemplo lo dbarker sugiere)
  4. tiene una bandera global "prueba", "depuración", "Puesta en marcha" o lo que sea que cambia el comportamiento de bajo nivel
  5. Introspect y retire los observadores
  6. añadir un método para su modelo que lleva a cabo una alternativa , versión no observada de la tarea (compartiendo la implementación con el método normal tanto como sea posible).

En este caso, yo diría que el # 3 es su mejor opción.

0

Como otros han insinuado; Me gustaría envolver la lógica no deseada en su Observer con una simple declaración if.

def after_create 
    send_email if RAILS_ENV == "production" 
end 
2

Cuando las pruebas se ejecutan en una aplicación que estoy trabajando, yo uso el siguiente:

Model.delete_observers 
1

que puede tomar el método fuera del observador;

MessageObserver.send(:remove_method, :after_create) 

Se detendrá el: after_create en MessageObserver, eliminándolo.

2

observadores de bloqueo para Rails 3 es simple:

Rails.configuration.active_record.observers = [] 
6

Otra puede tratar (carriles 3)

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

Esto resolvió totalmente el problema para mí. ¡Gracias! – Sixty4Bit

+0

¡esto también funciona para mí !, pero me gustaría agregar un condicional adicional de ARGV [0] == "db: migrar" porque es posible que en el futuro pueda escribir una tarea de rake que utilice a sus observadores, y puede olvidarse acerca de esta pequeña línea y jala tu cabello tratando de descubrir por qué tus observadores no corren durante tu nueva y elegante tarea de rake ... –

1

vine aquí en busca de la respuesta a la misma ... ninguno de los anteriores parece ser el truco (o implica agregar una lógica específica de migración a mi código de aplicación - boo).

Esto es lo que ocurrió con (un poco escaso que tiene que ir en cada migración relevante, pero ...)

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 
8

Como una bandera para el observador me gusta definir un descriptor de acceso clase llamada "desactivada" para que se lea así:

class ActivityObserver < ActiveRecord::Observer 
    observe :user 

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

lo puse como condición en las devoluciones de llamada sensibles

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

y acabo de vuelta a la bandera en cuando es necesario

ActivityObserver.disabled=true 
119

Rails 3.1 por último viene con API para esto: 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 

Dónde ORM podría ser, por ejemplo ActiveRecord::Base

+0

Esta es de lejos la mejor respuesta aquí :-) –

+0

Ninguno de estos se agacha para mí. Terminé con convertirlos en tareas de rake en application.rb – mhenrixon

+1

¿Qué usaría la mayoría de las personas en lugar de 'ORM'? –

1
User.skip_callback("create", :after, :send_confirmation_email) 

.... 

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

Más en esto:

Disabling Callbacks in Rails 3

Cuestiones relacionadas