How to detect attribute changes from model?

For Rails 5.1+, you should use active record attribute method: saved_change_to_attribute?

saved_change_to_attribute?(attr_name, **options)`

Did this attribute change when we last saved? This method can be invoked as saved_change_to_name? instead of saved_change_to_attribute?("name"). Behaves similarly to attribute_changed?. This method is useful in after callbacks to determine if the call to save changed a certain attribute.

Options

from When passed, this method will return false unless the original value is equal to the given option

to When passed, this method will return false unless the value was changed to the given value

So your model will look like this, if you want to call some method based on the change in attribute value:

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

And if you don't want to check for value change in callback, you can do the following::

class Claim < ApplicationRecord

  after_save: :do_this, if: saved_change_to_status?


  def do_this
    ..
    ..
  end

end

you can use this

self.changed

it return an array of all columns that changed in this record

you can also use

self.changes

which returns a hash of columns that changed and before and after results as arrays


You should look at ActiveModel::Dirty module: You should be able to perform following actions on your Claim model:

claim.status_changed?  # returns true if 'status' attribute has changed
claim.status_was       # returns the previous value of 'status' attribute
claim.status_change    # => ['old value', 'new value'] returns the old and 
                       # new value for 'status' attribute

claim.name = 'Bob'
claim.changed # => ["name"]
claim.changes # => {"name" => ["Bill", "Bob"]}

Oh! the joys of Rails!