Je voudrais créer une fonction de rappel dans les rails qui s'exécute après l'enregistrement d'un modèle.
J'ai ce modèle, Revendication qui a un attribut «statut» qui change en fonction de l'état de la revendication, les valeurs possibles sont en attente, approuvées, approuvées, rejetées
La base de données a «état» avec la valeur par défaut «en attente».
J'aimerais effectuer certaines tâches après la création du modèle la première fois ou la mise à jour d'un état à un autre, en fonction de l'état à partir duquel il change.
Mon idée est d'avoir une fonction dans le modèle:
after_save :check_state
def check_state
# if status changed from nil to pending (created)
do this
# if status changed from pending to approved
performthistask
end
Ma question est de savoir comment vérifier la valeur précédente avant le changement dans le modèle?
la source
dirty
appels fonctionnent dansafter_save
(à la fois dans Rails 2.3 et 3.x). Je l'ai utilisé plusieurs fois.after_commit
rappels introduits dans Rails 3.x. Ils y travailleront certainementafter_save
.after_save
est un rappel pour un état entreafter DML
etbefore_commit
. Vous pouvez mettre fin à l'ensemble de la transaction enafter_save
lançant une exception. Si vous voulez faire quelque chose après l'enregistrement sans affecter l'opération en cours, utilisezafter_commit
:-)vous pouvez utiliser ceci
self.changed
il renvoie un tableau de toutes les colonnes qui ont changé dans cet enregistrement
vous pouvez aussi utiliser
self.changes
qui renvoie un hachage des colonnes qui ont changé et des résultats avant et après sous forme de tableaux
la source
self.
sur ces derniers - vous pouvez simplement direchanged
etchanges
.self
lorsque vous êtes dans le modèle lui-même, mais vous pouvez les appeler sur n'importe quel objet avecobject.changed
etobject.changes
. :)Je vous recommande de jeter un œil à l'un des plugins de machine d'état disponibles:
L'un ou l'autre vous permettra de configurer les états et les transitions entre les états. Manière très utile et facile de gérer vos besoins.
la source
Pour Rails 5.1+, vous devez utiliser la méthode d'attribut d'enregistrement actif: saved_change_to_attribute?
Donc, votre modèle ressemblera à ceci, si vous voulez appeler une méthode basée sur le changement de valeur d'attribut:
class Claim < ApplicationRecord after_save :do_this, if: Proc.new { saved_change_to_status?(from: nil, to: 'pending') } after_save :do_that, if: Proc.new { saved_change_to_status?(from: 'pending', to: 'approved') } def do_this .. .. end def do_that .. .. end end
Et si vous ne voulez pas vérifier le changement de valeur dans le rappel, vous pouvez faire ce qui suit:
class Claim < ApplicationRecord after_save: :do_this, if: saved_change_to_status? def do_this .. .. end end
la source
J'ai vu la question se poser dans de nombreux endroits, alors j'ai écrit un minuscule rubygème pour cela, pour rendre le code un peu plus agréable (et éviter un million de déclarations if / else partout): https://github.com/ronna-s / on_change . J'espère que cela aide.
la source
Vous ferez bien mieux d'utiliser une solution bien testée telle que la gemme state_machine .
la source