Changing sate before saving to the database in Rails
Tags: ruby, rails
Published: 2021-01-09 23:36:58

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](https://guides.rubyonrails.org/active_record_callbacks.html) 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](https://api.rubyonrails.org/v6.1.0/classes/ActiveRecord/Callbacks.html), 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
```
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](https://rubular.com/). Be sure to add the "i" after the forward slash at [Rubular](https://rubular.com/). 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
```
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!