J'ai quelques modèles qui ont des rappels after_save. En général, c'est bien, mais dans certaines situations, comme lors de la création de données de développement, je souhaite enregistrer les modèles sans exécuter les rappels. Y a-t-il un moyen simple de le faire? Quelque chose qui ressemble à ...
Person#save( :run_callbacks => false )
ou
Person#save_without_callbacks
J'ai regardé dans la documentation Rails et je n'ai rien trouvé. Cependant, d'après mon expérience, les documents Rails ne racontent pas toujours toute l'histoire.
METTRE À JOUR
J'ai trouvé un article de blog qui explique comment supprimer les rappels d'un modèle comme celui-ci:
Foo.after_save.clear
Je n'ai pas pu trouver où cette méthode est documentée, mais elle semble fonctionner.
Foo.after_save.clear
supprimerait -il pas les rappels pour tout le modèle? Et puis comment proposez-vous de les restaurer?Réponses:
Cette solution est uniquement Rails 2.
Je viens juste d'enquêter et je pense avoir une solution. Il existe deux méthodes privées ActiveRecord que vous pouvez utiliser:
Vous allez devoir utiliser send pour appeler ces méthodes. exemples:
C'est certainement quelque chose que vous ne voudrez vraiment utiliser que dans la console ou lors de tests aléatoires. J'espère que cela t'aides!
la source
Utilisez
update_column
(Rails> = v3.1) ouupdate_columns
(Rails> = 4.0) pour ignorer les rappels et les validations. Aussi avec ces méthodes,updated_at
n'est pas mis à jour.http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update_column
# 2: Ignorer les rappels qui fonctionnent également lors de la création d'un objet
la source
:create_without_callbacks
: (Comment puis-je exécuter quelque chose de similaire? (Travaillé dans Rails2, supprimé dans Rails3).@person
ait une variable dans un contrôleur quelque part, cette solution signifie que les personnes lisant votre classe de modèle ne pourront pas comprendre les rappels. Ils verrontafter_create :something_cool
et penseront "génial, il se passe quelque chose de cool après la création!". Pour comprendre réellement votre classe de modèle, ils devront greper tous vos contrôleurs, à la recherche de tous les petits endroits où vous avez décidé d'injecter de la logique. Je n'aime pas ça> o <;;skip_callback ..., if: :skip_some_callbacks
parafter_create ..., unless: :skip_some_callbacks
pour l'exécuter correctement avec after_create.Actualisé:
La solution de @Vikrant Chaudhary semble meilleure:
Ma réponse originale:
voir ce lien: Comment ignorer les rappels ActiveRecord?
dans Rails3,
supposons que nous ayons une définition de classe:
Approche1:
Approach2: Lorsque vous voulez les ignorer dans vos fichiers rspec ou autre, essayez ceci:
REMARQUE: une fois que cela est fait, si vous n'êtes pas dans l'environnement rspec, vous devez réinitialiser les rappels:
fonctionne bien pour moi sur les rails 3.0.5
la source
rails 3:
la source
reset_callbacks
n'est pas:after_save
, mais plutôt:save
. apidock.com/rails/v3.0.9/ActiveSupport/Callbacks/ClassMethods/…Si l'objectif est simplement d'insérer un enregistrement sans callback ou validations, et que vous souhaitez le faire sans recourir à des gemmes supplémentaires, en ajoutant des vérifications conditionnelles, en utilisant RAW SQL ou en utilisant votre code existant de quelque manière que ce soit, envisagez d'utiliser un "shadow object "pointant vers votre table db existante. Ainsi:
Cela fonctionne avec toutes les versions de Rails, est threadsafe et élimine complètement toutes les validations et rappels sans aucune modification de votre code existant. Vous pouvez simplement lancer cette déclaration de classe juste avant votre importation réelle, et vous devriez être prêt à partir. N'oubliez pas d'utiliser votre nouvelle classe pour insérer l'objet, comme:
la source
Vous pouvez essayer quelque chose comme ceci dans votre modèle Person:
EDIT: after_save n'est pas un symbole, mais c'est au moins la 1000e fois que j'essaye d'en faire un.
la source
send
. KOODOSVous pouvez utiliser
update_columns
:la source
Le seul moyen d'empêcher tous les rappels after_save est que le premier retourne false.
Vous pourriez peut-être essayer quelque chose comme (non testé):
la source
Il semble qu'une façon de gérer cela dans Rails 2.3 (puisque update_without_callbacks est parti, etc.), serait d'utiliser update_all, qui est l'une des méthodes qui saute les rappels selon la section 12 du Guide Rails sur les validations et les rappels .
Notez également que si vous faites quelque chose dans votre callback after_, qui fait un calcul basé sur de nombreuses associations (c'est-à-dire un has_many assoc, où vous faites également accept_nested_attributes_for), vous devrez recharger l'association, au cas où dans le cadre de la sauvegarde , l'un de ses membres a été supprimé.
la source
https://gist.github.com/576546
vider simplement ce monkey-patch dans config / initializers / skip_callbacks.rb
puis
Project.skip_callbacks { @project.save }
ou semblable.
tout le crédit à l'auteur
la source
La plupart des
up-voted
réponses peuvent sembler déroutantes dans certains cas.Vous pouvez utiliser une simple
if
vérification si vous souhaitez ignorer un rappel, comme ceci:la source
Une solution qui devrait fonctionner sur toutes les versions de Rails sans utiliser de gemme ou de plugin consiste simplement à émettre des instructions de mise à jour directement. par exemple
Cela peut (ou non) être une option en fonction de la complexité de votre mise à jour. Cela fonctionne bien pour les drapeaux de mise à jour , par exemple sur un enregistrement de l' intérieur d' un rappel after_save (sans redéclencher le rappel).
la source
#{...}
.la source
Aucun de ces éléments ne pointe vers un
without_callbacks
plugin qui fait juste ce dont vous avez besoin ...http://github.com/cjbottaro/without_callbacks fonctionne avec Rails 2.x
la source
J'ai écrit un plugin qui implémente update_without_callbacks dans Rails 3:
http://github.com/dball/skip_activerecord_callbacks
La bonne solution, je pense, est de réécrire vos modèles pour éviter les rappels en premier lieu, mais si cela n'est pas pratique à court terme, ce plugin peut vous aider.
la source
Si vous utilisez Rails 2. Vous pouvez utiliser une requête SQL pour mettre à jour votre colonne sans exécuter de rappels et de validations.
Je pense que cela devrait fonctionner dans toutes les versions de rails.
la source
Lorsque j'ai besoin d'un contrôle total sur le rappel, je crée un autre attribut qui est utilisé comme commutateur. Simple et efficace:
Modèle:
Tester:
la source
Pour créer des données de test dans Rails, vous utilisez ce hack:
https://coderwall.com/p/y3yp2q/edit
la source
Vous pouvez utiliser la gemme de sauvegarde sournoise: https://rubygems.org/gems/sneaky-save .
Notez que cela ne peut pas aider à enregistrer des associations sans validations. Il renvoie l'erreur 'created_at cannot be null' car il insère directement la requête SQL contrairement à un modèle. Pour implémenter cela, nous devons mettre à jour toutes les colonnes générées automatiquement de db.
la source
J'avais besoin d'une solution pour Rails 4, alors j'ai trouvé ceci:
app / models / concern / save_without_callbacks.rb
dans n'importe quel modèle:
Ensuite vous pouvez:
ou
la source
Pourquoi voudriez-vous pouvoir faire cela en développement? Cela signifiera sûrement que vous construisez votre application avec des données non valides et, en tant que telle, elle se comportera de manière étrange et non comme vous vous y attendez en production.
Si vous souhaitez remplir votre base de données de développement avec des données, une meilleure approche serait de créer une tâche de râteau qui utilise le gem faker pour créer des données valides et les importer dans la base de données en créant autant ou peu d'enregistrements que vous le souhaitez, mais si vous êtes talon plié dessus et avoir une bonne raison, je suppose que update_without_callbacks et create_without_callbacks fonctionneront bien, mais lorsque vous essayez de plier les rails à votre guise, demandez-vous que vous avez une bonne raison et si ce que vous faites est vraiment une bonne idée.
la source
Une option consiste à avoir un modèle distinct pour de telles manipulations, en utilisant le même tableau:
(La même approche pourrait faciliter les choses pour contourner les validations)
Stéphan
la source
Une autre façon serait d'utiliser des hooks de validation au lieu de callbacks. Par exemple:
De cette façon, vous pouvez obtenir le do_something par défaut, mais vous pouvez facilement le remplacer avec:
la source
Quelque chose qui devrait fonctionner avec toutes les versions de
ActiveRecord
sans dépendre des options ou des méthodes activerecord qui peuvent exister ou non.TLDR: utilisez un "modèle d'activation d'enregistrement différent" sur la même table
la source
Pour les rappels personnalisés, utilisez un
attr_accessor
et ununless
dans le rappel.Définissez votre modèle comme suit:
Et puis, si vous devez sauvegarder l'enregistrement sans toucher les
after_save
rappels que vous avez définis, définissez l'skip_after_save_callbacks
attribut virtuel surtrue
.la source
Ce n'est pas la manière la plus propre, mais vous pouvez envelopper le code de rappel dans une condition qui vérifie l'environnement Rails.
la source