J'ai l'association suivante dans mon application:
# Page
belongs_to :status
Je veux exécuter un rappel à tout moment le status_id
d'un page
a changé.
Donc si page.status_id
va de 4 à 5, je veux pouvoir attraper ça.
Comment le faire
class Page < ActiveRecord::Base
before_save :do_something, if: :will_save_change_to_status_id?
private
def do_something
# ...
end
end
Le commit qui a changé ActiveRecord :: Dirty est ici: https://github.com/Rails/rails/commit/16ae3db5a5c6a08383b974ae6c96faac5b4a3c81
Voici un article de blog sur ces modifications: https://www.ombulabs.com/blog/Rails/upgrades/active-record-5-1-api-changes.html
Voici le résumé que je me suis fait sur les modifications apportées à ActiveRecord :: Dirty dans Rails 5.1+:
https://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/Dirty.html
Après avoir modifié un objet et avant d’enregistrer dans la base de données, ou dans le filtre before_save
:
changes
devrait maintenant être changes_to_save
changed?
Devrait maintenant être has_changes_to_save?
changed
devrait maintenant être changed_attribute_names_to_save
<attribute>_change
Devrait maintenant être <attribute>_change_to_be_saved
<attribute>_changed?
Devrait maintenant être will_save_change_to_<attribute>?
<attribute>_was
Devrait maintenant être <attribute>_in_database
Après avoir modifié un objet et après avoir sauvegardé dans la base de données, ou dans le filtre after_save
:
saved_changes
(Remplace previous_changes
)saved_changes?
saved_change_to_<attribute>
saved_change_to_<attribute>?
<attribute>_before_last_save
class Page < ActiveRecord::Base
before_save :do_something, if: :status_id_changed?
private
def do_something
# ...
end
end
Cela utilise le fait que le rappel before_save
Peut être exécuté de manière conditionnelle en fonction de la valeur de retour d'un appel de méthode. La méthode status_id_changed?
Provient de ActiveModel :: Dirty , ce qui nous permet de vérifier si un attribut spécifique a été modifié en ajoutant simplement _changed?
Au nom de l'attribut.
Lorsque la méthode do_something
Doit être appelée, vous répondez à vos besoins. Cela peut être before_save
Ou after_save
Ou n'importe lequel des le ActiveRecord :: Callbacks défini .
Le attribute_changed?
est obsolète dans Rails 5.1, utilisez maintenant simplement will_save_change_to_attribute?
.
Pour plus d'informations, voir this issue .
Essaye ça
after_validation :do_something, if: ->(obj){ obj.status_id.present? and obj.status_id_changed? }
def do_something
# your code
end
Référence - http://apidock.com/Rails/ActiveRecord/Dirty