Rails, using the dirty or changed? flag with after_commit
Asked Answered
P

3

14

I heard rails has a dirty/change flag. Is it possible to use that in the after_commit callback?

In my user model I have:

after_commit :push_changes

In def push_changes I would like a way to know if the name field changed. Is that possible?

Putrescine answered 23/8, 2011 at 1:11 Comment(0)
O
6

You can do a few things to check...

First and foremost, you can check an individual attribute as such:

user = User.find(1)
user.name_changed? # => false
user.name = "Bob"
user.name_changed? # => true

But, you can also check which attributes have changed in the entire model:

user = User.find(1)
user.changed     # => []
user.name = "Bob"
user.age = 42
user.changed     # => ['name', 'age']

There's a few more things you can do too - check out http://api.rubyonrails.org/classes/ActiveModel/Dirty.html for details.

Edit:

But, given that this is happening in an after_commit callback, the model has already been saved, meaning knowledge of the changes that occurred before the save are lost. You could try using the before_save callback to pick out the changes yourself, store them somewhere, then access them again when using after_commit.

Overlay answered 23/8, 2011 at 1:17 Comment(2)
Right, sorry, missed that part of it. After saving the model the changed attributes are wiped out, so this would be pretty useless... Could you yourself store the changed attributes using before_save, for instance, and then retrieve them afterwards?Overlay
changed?/changes will work in after_save, but not after_commit. Instead, you can use previous_changes in after_commit- see @Jonathan's answerAllopathy
Z
36

You can use previous_changes in after_commit to access a model's attribute values from before it was saved.

see this post for more info: after_commit for an attribute

Zorina answered 29/5, 2013 at 21:0 Comment(1)
activerecord is cool, I just had one example of previous_changes - t.co/yjCLEdDHYHEnfold
O
6

You can do a few things to check...

First and foremost, you can check an individual attribute as such:

user = User.find(1)
user.name_changed? # => false
user.name = "Bob"
user.name_changed? # => true

But, you can also check which attributes have changed in the entire model:

user = User.find(1)
user.changed     # => []
user.name = "Bob"
user.age = 42
user.changed     # => ['name', 'age']

There's a few more things you can do too - check out http://api.rubyonrails.org/classes/ActiveModel/Dirty.html for details.

Edit:

But, given that this is happening in an after_commit callback, the model has already been saved, meaning knowledge of the changes that occurred before the save are lost. You could try using the before_save callback to pick out the changes yourself, store them somewhere, then access them again when using after_commit.

Overlay answered 23/8, 2011 at 1:17 Comment(2)
Right, sorry, missed that part of it. After saving the model the changed attributes are wiped out, so this would be pretty useless... Could you yourself store the changed attributes using before_save, for instance, and then retrieve them afterwards?Overlay
changed?/changes will work in after_save, but not after_commit. Instead, you can use previous_changes in after_commit- see @Jonathan's answerAllopathy
A
4

Since Rails 5.1, in after_commit you should use saved_change_to_attribute?

Ref: Rails 5.1.1 deprecation warning changed_attributes

Abeyant answered 16/8, 2021 at 2:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.