# 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 end1
2
3
4
5
6
7
8
9
10
11
12The 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 end1
2
3
4
5
6
7Callbacks 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 end1
2
3
4
5
6
7
8
9
10
11
12
13
14
15It 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,:updateThis 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 end1
2
3
4
5
6
7
8
9
10
11
12
13after_validation
Actions that trigger it:
:create,:updateThis 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 end1
2
3
4
5
6
7
8
9
10
11before_save
Actions that trigger it:
:create,:updateThis 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 end1
2
3
4
5
6
7
8
9
10
11around_save
Actions that trigger it:
:create,:updateThis 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 end1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23When 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 saved1
2
3
4
5
6From the above output, you see that the
before_saveblock is called first, next thearound_saveblock. 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 thecall_around_savemethod which logs the last line and then passes control to theafter_savecallback.before_create
Actions that trigger it:
:createThis callback is the same as the
before_save. The only difference is that it is triggered only by thecreateaction.Note: In a creation operation, the
before_saveis usually called before thebefore_createcallback.around_create
Actions that trigger it:
:createThis callback is the same as the
around_save. The difference between them is that it is triggered only by thecreateaction.after_create
Actions that trigger it:
:createThis callback is the same as the
after_save. The only difference is that it is triggered only by thecreateaction.after_save
Actions that trigger it:
:create,:updateThis 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 end1
2
3
4
5
6
7
8
9
10
11before_update
Actions that trigger it:
:updateThis callback is the same as the
before_save. The difference is that it is triggered only by theupdateaction.around_update
Actions that trigger it:
:updateThis callback is the same as the
around_save. The difference between them is that it is triggered only by theupdateaction.after_update
Actions that trigger it:
:updateThis callback is the same as the
after_save. The only difference is that it is triggered only by theupdateaction.before_destroy
Actions that trigger it:
:destroyThis 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_destroycallback 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:
:destroyThis callback works like the
around_savebut only for adestroyaction.after_destroy
Actions that trigger it:
:destroyThis 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,:destroyThis callback is called after an object has been created, updated or destroyed. It can replace the
after_save,after_update,after_updateorafter_destroycallbacks. You use this method when you want to run the same method when any of these 3 actions are executed.