ActiveRecord Dirty Checks

Sometimes in Rails applications we need to perform an action based on a change in a particular attribute of a model.

For example, suppose we have an event management site and we need to notify the event attendees that the privacy of an event has changed. The ActiveRecord::AttributeMethods::Dirty check comes in handy in such scenarios.

The Event model has an enum attribute of privacy, and privacy can have the following values:

  1. Private (invite only) (DEFAULT VALUE)
  2. Public (open for organizational users)
  3. Open (open for the general public)

In the after_save callback in the Event model, we’ll have following callbacks:

1
2
after_save    :notify_attendees_of_privacy_change, if: :saved_change_to_privacy?
before_save   :destroy_outsiders, if: :will_save_change_to_privacy?
1
2
3
def notify_attendees_of_privacy_change
 EventMailer.notify_attendees_of_privacy_change(self).deliver_later
end
1
2
3
def destroy_outsiders
  outsiders.destroy_all if outsiders.exists?
end

Moreover, ActiveModel::Dirty provides us with some other helper methods too, such as:

1
2
3
4
5
6
7
8
9
10
11
event = Event.create(title: 'Birthday Party', privacy: 0)

event.title = 'Farewell'

# Before saving the Event object, the following are the dirty checks:

event.changed?        # => true
event.title_changed?  # => true
event.title_changed?(from: 'Birthday Party', to: 'Farewell') # => true
event.title_was       # => 'Birthday Party'
event.title_change    # => ['Birthday Party', 'Farewell']

For more details, here are the official docs on ActiveModel::Dirty, ActiveRecord::AttributeMethods::Dirty - happy checking!