ActiveRecord Callbacks with Rails
Can you imagine accidentally saving bad data into your database? If bad data were to get into your database, you could add additional logic into your controllers to handle them. But what if we could somehow handle that before an object is created?
Along with validations, using callbacks will prevent bad data from being inserted into your database.
What is a callback?
A callback is a method that gets called during an object’s specific moment in its lifecycle. An object’s lifecycle is from its creation to its destruction In-between the creation and destruction of an object will be the READ and UPDATE moments.
Step 1
In order to use a callback, we have to define one in a model that will be using that specific callback. For example, if we have a web application that lets people create accounts, we might have something like:
class User < ApplicationRecord
validates_presence_of :first_name, :last_name private
def ensure_name_is_titlecase
self.first_name.titlecase
self.last_name.titlecase
end
end
Sometimes users could accidentally type their names with lowercase letters. Then on their homepage, we could try to welcome the user but the user sees that their name is lowercased! We would want a method to prevent that embarrassment.
Step 2
After defining the method that we need, we would let ActiveRecord know when to execute ensure_name_is_titlecase
.
class User < ApplicationRecord
validates_presence_of :first_name, :last_name
before_validation :ensure_name_is_titlecase private
def ensure_name_is_titlecase
self.first_name.titlecase
self.last_name.titlecase
end
end
The macro, before_validation
suggests that the method that it takes as an input will be executed every time before there is a validation.
Here is a list of common ActiveRecord methods that will trigger a validation:
save
save!
update
update!
valid?
With before_validation :ensure_name_is_titlecase
, the ensure_name_is_titlecase
method will run before every validation method.
Step 3
But what if we don’t want our program to waste time running certain callbacks? We could specify which lifecycle events to run the callbacks in addition to just before any methods that validates!
class User < ApplicationRecord
validates_presence_of :first_name, :last_name
before_validation :ensure_name_is_titlecase, on: [ :create, :update ] private
def ensure_name_is_titlecase
self.first_name.titlecase
self.last_name.titlecase
end
end
In this snippet, we specify that we want the callback to only run on the create and update lifecycle events. This way, we won’t run unnecessary methods!
Common Callback Macros
When Creating an Object
before_validation
after_validation
before_save
after_save
before_create
after_create
When Updating an Object
before_validation
after_validation
before_save
after_save
before_update
after_update
When Destroying an Object
before_destroy
after_destroy