38

J'utilise restful_authentication dans mon application. Je crée un ensemble d'utilisateurs par défaut en utilisant une tâche rake, mais chaque fois que j'exécute la tâche, un email d'activation est envoyé à cause de l'observateur associé à mon modèle d'utilisateur. Je définis les champs d'activation lorsque je crée les utilisateurs, donc aucune activation n'est nécessaire. Quelqu'un sait-il qu'il est facile de contourner les observateurs tout en exécutant une tâche de rake afin qu'aucun courriel ne soit envoyé lorsque je sauvegarde l'utilisateur?Façon simple d'éteindre les observateurs pendant la tâche de râteau?

Merci.

Répondre

7

Vous pouvez ajouter un accesseur à votre modèle d'utilisateur, quelque chose comme « skip_activation » qui ne serait pas besoin d'être sauvé, mais persistera dans la session, puis vérifiez le drapeau dans l'observateur. Quelque chose comme

class User 
    attr_accessor :skip_activation 
    #whatever 
end 

Puis, l'observateur:

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

Il n'y a pas un moyen facile de désactiver les observateurs que je connais, mais il semble possible d'ajouter une logique à votre observateur de ne pas envoyer un e-mail lorsque le code d'activation est réglé ...

2

En général, pour ce genre de situations, vous pouvez:

  1. Mettre en place un objet fantaisie à « absorber » le comportement indésirable
  2. Avoir un drapeau accessible de l'extérieur/commutateur que les observateurs respectent pour inhiber le comportement
  3. Ajouter logique à l'observateur de décevoir ct lorsque le comportement est inutile en général (par ex. ce dbarker suggère)
  4. ont un « test » global drapeau, « debug », « startup » ou quoi qui change le comportement de bas niveau
  5. Introspect et retirer les observateurs
  6. Ajouter une méthode à votre modèle qui effectue une alternative , version non observée de la tâche (partage de l'implémentation avec la méthode normale autant que possible).

Dans ce cas, je dirais que le # 3 est votre meilleur pari.

0

Comme d'autres l'ont laissé entendre; J'envelopperais la logique non désirée dans votre observateur avec une simple instruction if.

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

Lorsque les tests en cours d'exécution sur une application je travaille, j'utilise les éléments suivants:

Model.delete_observers 
1

Vous pouvez prendre la méthode hors de l'observateur;

MessageObserver.send(:remove_method, :after_create) 

Arrêter le: after_create sur MessageObserver en le supprimant.

2

pour Rails observateurs Désactivation 3 il est simple:

Rails.configuration.active_record.observers = [] 
6

Un autre, vous pouvez essayer (rails 3)

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

Cela a totalement résolu le problème pour moi. Merci! – Sixty4Bit

+0

cela fonctionne pour moi aussi !, mais je voudrais ajouter des conditions supplémentaires de ARGV [0] == "db: migrate" parce que vous pouvez à l'avenir écrire une tâche râteau qui utilise vos observateurs, et vous pouvez oublier à propos de cette petite petite ligne et tirez vos cheveux en essayant de comprendre pourquoi vos observateurs ne courent pas pendant votre nouvelle tâche rake fantaisie ... –

1

Je suis venu ici à la recherche de la réponse à la même ... aucune de ce qui précède semblait faire l'affaire (ou impliquer l'ajout de la logique spécifique à la migration à mon code de l'application - boo).

Voici ce que je suis venu avec (un peu boiteux qu'il a besoin d'aller dans chaque migration pertinente, mais ...)

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

En tant que drapeau pour l'observateur que j'aime définir un accesseur de classe appelée "désactivé" il se lit comme ceci:

class ActivityObserver < ActiveRecord::Observer 
    observe :user 

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

je l'ai mis comme condition dans les callbacks sensibles

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

et je tourne juste le drapeau en cas de besoin

ActivityObserver.disabled=true 
119

Rails 3.1 vient enfin avec l'API pour cela: 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 pourrait par exemple être ActiveRecord::Base

+0

C'est de loin la meilleure réponse ici :-) –

+0

Ni l'un ni l'autre ne s'accroupit pour moi. J'ai fini par les transformer en applications.rb – mhenrixon

+1

Qu'est-ce que la plupart des gens utiliseraient à la place de 'ORM'? –

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

.... 

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

Plus sur ce:

Disabling Callbacks in Rails 3

Questions connexes