# Callbacks

  • Introduction

    Callbacks are methods that get called at certain moments of an object's life cycle. With callbacks it is possible to write code that will run whenever an Active Record object is created, saved, updated, deleted, validated, or loaded from the database.

  • Callback Registration

    In order to use the available callbacks, you need to register them. You can implement the callbacks as ordinary methods and use a macro-style class method to register them as callbacks:

    class User < ApplicationRecord
      validates :login, :email, presence: true
    
      before_validation :ensure_login_has_a_value
    
      private
        def ensure_login_has_a_value
          if login.nil?
            self.login = email unless email.blank?
          end
        end
    end
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    The macro-style class methods can also receive a block. Consider using this style if the code inside your block is so short that it fits in a single line:

    class User < ApplicationRecord
      validates :login, :email, presence: true
    
      before_create do
        self.name = login.capitalize if name.blank?
      end
    end
    
    1
    2
    3
    4
    5
    6
    7

    Callbacks can also be registered to only fire on certain life cycle events:

    class User < ApplicationRecord
      before_validation :normalize_name, on: :create
    
      # :on takes an array as well
      after_validation :set_location, on: [ :create, :update ]
    
      private
        def normalize_name
          self.name = name.downcase.titleize
        end
    
        def set_location
          self.location = LocationService.query(self)
        end
    end
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

    It is considered good practice to declare callback methods as private. If left public, they can be called from outside of the model and violate the principle of object encapsulation.

  • before_validation

    Actions that trigger it: :create:update

    This callback is used before the model validation takes place. For example, for our Article model, if we want to set the title a value in the case that it is empty, we can do in a before_validation.

    class Article < ApplicationRecord
      validates :title, presence: true
    
      before_validation :ensure_title_has_a_value
    
      private
    
      def ensure_login_has_a_value
        if title.nil?
          self.title = "Title #{Title.all.count + 1}"
        end
      end
    end
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
  • after_validation

    Actions that trigger it: :create:update

    This callback is used after the model validation takes place. For our Article model, if we want to capitalize the title of the article, we can do in the after_validation.

    class Article < ApplicationRecord
      validates :title, presence: true
    
      after_validation :capitalize_title
    
      private
    
      def capitalize_title
        self.title = title.capitalize
      end
    end
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
  • before_save

    Actions that trigger it: :create:update

    This callback is called before the object is saved to the database. For our Article model, if we want to capitalize the title of the article, we can do in the after_validation.

    class Article < ApplicationRecord
      validates :title, presence: true
    
      before_save :log_message
    
      private
    
      def log_message
        puts "You are about to save an article"
      end
    end
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
  • around_save

    Actions that trigger it: :create:update

    This callback is called around the saving the object and inside the before_save and after_save actions. Please note that you need to put a yield in the around_save method so that the action(save) can be performed. For example, if we have an article with the callbacks below;

    class Article < ApplicationRecord
      validates :title, presence: true
    
      before_save :call_before_save
      after_save :call_after_save
      around_save :call_around_save
    
      private
    
      def call_before_save
        puts 'before article is saved'
      end
    
      def call_after_save
        puts 'after article is saved'
      end
    
      def call_around_save
        puts 'in around article save'
        yield # Article saved
        puts 'out around article save'
      end
    end
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23

    When we initialize and save a new Article. We should have the following output;

    article = Article.new(title: 'My title')
    article.save
      before article is saved
      in around article save
      out around article save
      after article is saved
    
    1
    2
    3
    4
    5
    6

    From the above output, you see that the before_save block is called first, next the around_save block. The method first logs the first line, then yields to the save action so the article can be saved to the database. After the save action is complete, control is then returned back to the call_around_savemethod which logs the last line and then passes control to the after_savecallback.

  • before_create

    Actions that trigger it: :create

    This callback is the same as the before_save. The only difference is that it is triggered only by the create action.

    Note: In a creation operation, the before_save is usually called before the before_create callback.

  • around_create

    Actions that trigger it: :create

    This callback is the same as the around_save. The difference between them is that it is triggered only by the create action.

  • after_create

    Actions that trigger it: :create

    This callback is the same as the after_save. The only difference is that it is triggered only by the create action.

  • after_save

    Actions that trigger it: :create:update

    This callback is the executed after the object has been saved to the database. It is mostly used when you want to log database changes or track who made changes and in some case, make api call to a third party service

    class Article < ApplicationRecord
      validates :title, presence: true
    
      after_save :tell_salesforce_i_created_a_new_article
    
      private
    
      def tell_salesforce_i_created_a_new_article
        puts "Send a message to salesforce via HTTPS with my details"
      end
    end
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
  • before_update

    Actions that trigger it: :update

    This callback is the same as the before_save. The difference is that it is triggered only by the update action.

  • around_update

    Actions that trigger it: :update

    This callback is the same as the around_save. The difference between them is that it is triggered only by the update action.

  • after_update

    Actions that trigger it: :update

    This callback is the same as the after_save. The only difference is that it is triggered only by the update action.

  • before_destroy

    Actions that trigger it: :destroy

    This callback is triggered before an object is deleted from the database. You can use this to check for relationships that might be affected by its unavailability and either update those relationships or stop this action. In the case of our articles, if we have a table that saves medias or files associated with it, we can use the before_destroy callback to check that this article doesn't have a relationship saved in that table. If it exists, we can stop the action from going forward.

  • around_destroy

    Actions that trigger it: :destroy

    This callback works like the around_save but only for a destroy action.

  • after_destroy

    Actions that trigger it: :destroy

    This callback is triggered after an object has been deleted. Mostly utilized for cleanups. It can be used to update records, make an API call to a 3rd party service to notify it that the object has been deleted or trigger a background job.

  • after_commit/after_rollback

    Actions that trigger it: :create:update:destroy

    This callback is called after an object has been created, updated or destroyed. It can replace the after_saveafter_updateafter_update or after_destroy callbacks. You use this method when you want to run the same method when any of these 3 actions are executed.