简体   繁体   中英

Testing attribute_changed? VS. previous_changes in checking if a specific attribute changed (Rails), behaves differently

Apart from the return type specified by the docs, I was testing the difference between the 2 following lines in 2 different methods in after_save :

[:attribute_1, :attribute_2].any? {|a| self.send("#{a}_changed?")}

[:attribute_1, :attribute_2].any? {|attribute| self.previous_changes.key? attribute.to_s}

model.save! is called several times, but to my surprise, the first line returned true when one of the attributes was changed, but the second returned false and previous_changes is an empty hash. Could someone explain why this might happen?

Rails Version: '3.2.22.1'

Previous changes are prefilled after the model has been saved (and after_save callback is part of this process)

If you want the same behaviour, you're probably looking for changes method. Using it will return the results you're expecting.

According to the ActiveModel::Dirty documentation (it has the same behaviour in Rails 3)

person = Person.new
person.name = 'Bob'
person.name_changed?  # => true
person.changes        # => {"name" => [nil, "Bill"]}
person.save

person.name_changed?     # => false
person.changes           # => {}
person.previous_changes  # => {"name" => [nil, "Bill"]}
person.reload!
person.previous_changes  # => {}

But if you try to check the same in the after_commit callback, then you get the different results, since after_commit is called after the model is saved. Thus, previous_changes will be prefilled, but changes will be empty.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM