Comment faire pour enregistrer un modèle sans rappels dans les Rails
J'ai besoin de calculer des valeurs lors de l'enregistrement d'un modèle dans les Rails. J'appelle donc calculate_averages
comme un rappel pour un Survey
classe:
before_save :calculate_averages
Cependant, de temps en temps (et d'abord j'ai 10k enregistrements qui ont besoin de cette opération) j'ai besoin de mettre à jour manuellement toutes les moyennes pour chaque enregistrement. Pas de problème, j'ai le code suivant:
Survey.all.each do |survey|
survey.some_average = (survey.some_value + survey.some_other_value) / 2.to_f
#and some more averages...
survey.save!
end
Avant même l'exécution de ce code, je suis inquiet du calculate_averages
va devenir appelé et dupliquer ce et même, probablement, la cause de quelques problèmes avec la façon dont je fais les choses. Ok, donc je pense que, bien, je vais juste ne rien faire et laisser calculate_averages
appelée et faire sa chose. Problème il y a, d'abord, est-il un moyen de forcer les rappels à obtenir, même si vous n'avez pas fait de modifications à l'enregistrement?
Deuxièmement, la façon dont les moyennes sont calculées c'est loin plus efficace tout simplement de ne pas laisser les rappels appelée à tous et ne les moyennes pour tout à la fois. Est-ce possible de ne pas laisser les rappels appelée?
- Si vous avez 10k enregistrements à mettre à jour, alors pourquoi ne pas contourner AR complètement et il suffit de faire une simple mise à JOUR SQL? Surtout si vous souhaitez ignorer les rappels.
- J'ai simplifié les calculs j'ai besoin de le faire, mais ils sont complexes et dépendent d'autres dossiers de trop. J'ai besoin de Ruby pour cela.
Vous devez vous connecter pour publier un commentaire.
Je crois que ce que vous demandez peut être réalisé avec
ActiveSupport::Rappels
. Jetez un oeil àset_callback
etskip_callback
.Afin de "forcer les rappels à obtenir, même si vous n'avez pas fait de modifications à l'enregistrement", vous devez vous inscrire sur le rappel d'un événement par exemple
save, validate etc.
.De sauter le
before_save
rappel, vous feriez:Merci de référence liés
ActiveSupport::Rappels
sur les autres options, telles que les conditions et les blocs deset_callback
etskip_callback
.before_save
de rappel?Pour désactiver l'en-masse rappels utiliser...
Puis, afin de leur permettre...
Cette saute/jeux pour toutes les instances.
skip_callback
de commande. Le premier argument n'est pas le nom de la méthode que vous avez définie, c'est l'une des phases de rappel par exemple.save
,validate
,commit
, etc. La syntaxe correcte pour ce seraitSurvey.skip_callback(:save, :before, :calculate_averages)
Voir: api.rubyonrails.org/classes/ActiveSupport/Callbacks/...update_column
est unActiveRecord
fonction qui ne lancez pas de rappels, et elle n'a pas d'exécuter la validation.update_all
est similaire, et me permet de mettre à jour plusieurs colonnes à la fois.update
appels pour chaque enregistrement.Si vous voulez conditionnellement ignorer les rappels après vérification pour chaque enquête, vous pouvez écrire votre propre méthode.
Pour ex.
`
`
`
`
`
`
Son un peu bidouille mais l'espoir va travailler pour vous.
j'espère que c'est ce que vous cherchez.
https://stackoverflow.com/a/6587546/2238259
Pour votre deuxième question, je soupçonne il serait préférable d'inspecter lors de ce calcul qui doit arriver, ce serait mieux si elle pourrait être traitée dans le lot à un moment où le trafic réseau est à son creux.
EDIT: Oups. J'ai effectivement trouvé 2 liens, mais a perdu le premier, apparemment. J'espère que vous avez fixé.
survey.update_all(field: value)
mécanisme qui n'invoquent pas les rappels après la mise à jour.Pour Rails 3
ActiveSupport::Callbacks
vous donne le contrôle nécessaire. Vous pouvezreset_callbacks
en masse, ou de l'utilisationskip_callback
pour désactiver judicieusement comme ceci:...après quoi vous pouvez agir sur le Vote des instances avec
:add_points_to_user
inhibéeNe fonctionne pas pour les Rails 5
Fonctionne pour les Rails 5
https://github.com/thoughtbot/factory_bot/issues/931