DEV Community

rwparrish
rwparrish

Posted on • Updated on

Changing sate before saving to the database in Rails

In this blog, we're going to look at how to change an object's state immediately preceding saving it to the database in an RoR app.

The method that we will be using is actually a callback that is provided by ActiveRecord called before_save.

So, what's a callback then?

The official Ruby on Rails documentation says, "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."

So, what's an ActiveRecord callback then?

Again, exploring the documentation, we read, "Callbacks are hooks into the life cycle of an Active Record object that allow you to trigger logic before or after a change in the object state."

Take a look at the code below:

class User < ApplicationRecord
  has_many :articles
  validates :username, presence: true, uniqueness: { case_sensitive: false }, 
                      length: { minimum: 3, maximum: 25 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i                 
  validates :email, presence: true, uniqueness: { case_sensitive: false }, 
                    length: { maximum: 105 },
                    format: { with: VALID_EMAIL_REGEX }
end
Enter fullscreen mode Exit fullscreen mode

In the above code snippet, you can see that there is a constant assigned a some regex - VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i. This constant is then used to validate the format of email address taken in from the user.

For a neat little exercise, copy \A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/ and paste it here. Be sure to add the "i" after the forward slash at Rubular. Try entering some example and non-example email addresses. For example, try entering "janedoe@example.com" and "email.com". Pretty cool, huh?

So we can see that email addresses are being checked for proper email format. However, the letters' case in the email addresses is not being checked. This brings us to the before_save callback.

Check out the code below:

class User < ApplicationRecord
  before_save { self.email = email.downcase }
  has_many :articles
  validates :username, presence: true, uniqueness: { case_sensitive: false }, 
                      length: { minimum: 3, maximum: 25 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i                 
  validates :email, presence: true, uniqueness: { case_sensitive: false }, 
                    length: { maximum: 105 },
                    format: { with: VALID_EMAIL_REGEX }
end
Enter fullscreen mode Exit fullscreen mode

Notice this line - before_save { self.email = email.downcase }. Here we are referencing the email field associated with each object before saving said object so we must append the self keyword to the email we want to reference. This self is referencing each object of the User class so when the computer comes to the email field of any of these objects, it runs the downcase method on that field and then saves the object. We can now be sure that the email address will have proper formatting AND letter case before being saved to the database!

Recap

This blog covered a bit of regex and introduced you to the ActiveRecord callback before_save. With before_save, we can change the state of an object right before the object is saved to the database and in this case, it was used to execute a block of code that downcased all the letters in email addresses.

I hope you learned something and happy coding!

Top comments (0)