Thursday 15 April 2021

Rails ActiveRecord Callbacks – PART 1


 

Introduction

Active Record Callback's are very effective and quite useful in Ruby on Rails. Equally, they can be the allusive and invisible sources of bugs.

In this blog, we will be looking at the basics of ActiveRecord Callbacks.

What is a callback?

It is a method that get called at certain moment of an object’s life cycle.

What is an object life cycle?

When we do a normal operation in the rails application, objects may be createdupdated, and destroyed. These life cycle actions are called as object life cycle.

An Active Record provides hooks (called callbacks) into this object life cycle so that you can control your application and its data. 

What does the callbacks do?

Callback is basically just a way to trigger logic before, after or around a change to the object’s state. This allows you to execute any arbitrary code automatically whenever any event occurs.

By using the callbacks, We can write the code that will run whenever an Active Record Object is Initialising, Loading, Validating, Saving, Creating, Updating, and Deleting from the database.

Callbacks Registration

To use the available callbacks, you need to register them as callbacks. So There are two different ways in callbacks registration,

First, you can define a method to be called,

class TestCallback < ApplicationRecord
  # before_validation is one of the macro-style class method
  before_validation :check_before_validation
 
  private
  # We registered the below ordinary method as callback by using macro-style class method
  def check_before_validation
    puts 'Inside before validations.'
  end
end


Second, you can use the macro style. It also receive a block and use this style if the code inside the block is so short and that fits in a single line.

class TestCallback < ApplicationRecord
  # The before_validation(macro-style class method) is registered as a block.
  before_validation do
    puts 'Inside before validations.'
  end
end


We can also be register the callbacks to fire on certain life cycle events. For example, below code will register the callback method check_before_validation to run only on creating a new record.

class TestCallback < ApplicationRecord
  # The below callback is only fire on "create" life cycle event
  before_validation :check_before_validation, on: :create
 
  private
  def check_before_validation
    puts 'Inside before validations.'
  end
end


It is a good practice to declare the callback methods as protected or private. If kept public, It can be called from outside of the model and violate the principle of object encapsulation. See https://www.rubyguides.com/2018/10/method-visibility/ to learn more about method visibility.

Available Callbacks & Order of Operations

Below are the list of all available Active Record Callbacks listed in the order in which they will get executed during the respective object life cycle.

Creating an Object

  • before_validation
  • after_validation
  • before_save
  • around_save
  • before_create
  • around_create
  • after_create
  • after_save
  • after_create_commit
  • after_commit/after_rollback

Updating an Object

  • before_validation
  • after_validation
  • before_save
  • around_save
  • before_update
  • around_update
  • after_update
  • after_save
  • after_update_commit
  • after_commit/after_rollback

Destroying an Object

  • before_destroy
  • around_destroy
  • after_destroy
  • after_destroy_commit
  • after_commit/after_rollback

Finding an Object

  • after_find
  • after_initialize

Initializing an Object

  • after_initialize

Touching an Object

  • after_touch

Triggering Callbacks

The following ActiveRecord methods trigger callbacks to run,

Creating a Record

  • save
  • save!
  • save(validate: false)
  • create
  • create!

Updating a Record

  • save
  • save!
  • save(validate: false)
  • update_attribute
  • update
  • update!
  • toggle!

Destroying Record

  • destroy
  • destroy!
  • destroy_all

Finding Record

  • all
  • first
  • find
  • find_by
  • find_by_*
  • find_by_*!
  • find_by_sql
  • last
  • new

Intializing Record

  • new

Validating Record

  • valid?

Touching Record

  • touch

Note

  • before_validation & after_validation can be skipped with object.save(validate: false).
  • The after_initialize callback is triggered every time a new object is initialized.

Skipping Callbacks

The following ActiveRecord methods will skip any callbacks defined in the model from running.

  • decrement!
  • decrement_counter
  • delete
  • delete_all
  • increment!
  • increment_counter
  • update_column
  • update_columns
  • update_all
  • update_counters

These methods should be used with caution, bypassing them without understanding the potential implications may lead to invalid data.

No comments:

Post a Comment