Rails [attribute_name]_previously_changed? accepts :from and :to arguments


As mentioned in the title *_previously_changed? accepts :from and :to keyword arguments like *_changed?. So before understanding what previously_changed? does let’s understand how changed? functions.

car = Car.new
car.changed?                                      # => false
car.company = "Tesla"
car.changed?                                      # => true
car.company_changed?                              # => true
car.company_changed?(from: nil, to: "Tesla")      # => true

As described in the API documentation changed? returns true if any of the attributes has unsaved changes, false otherwise. So when we create a new Car instance and check if it’s value has changed? it will return false. But assigning the car object a company value Tesla and then checking if it’s changed? , it returns true.
changed? can also be used with the attributes as shown in the above example i.e. company_changed?. And also with the argument :to and :from , to check specifically if the car’s company changed from nil to Tesla as shown in the example.

changed? serves the purpose well when the values are unsaved changes. What happens if we save the changes.

car.save
car.changed?         # => false
car.company_changed? # => false

It returns a false value. So here is where previously_changed? comes into play. previously_changed? returns true if any of the attributes has saved changes, false otherwise. Let’s have a look at some examples.

car.company_previously_changed?                               # => true
car.company_previously_changed?(from: nil, to: "Tesla")       # => true

We can see here that running [attribute_name]_previously_changed? gives a true after the company name is saved for the car instance. And keyword argument :from and :to can be used in a similar fashion as in changed?. But using this feature we have to be wary that an instance reload may render this false.

car.reload
car.company_previously_changed?                               # => false
car.company_previously_changed?(from: nil, to: "Tesla")       # => false