Validating Models and Using Callbacks

Tutorial 4 of 5

Introduction

Goal of the Tutorial

This tutorial aims to provide an in-depth understanding of validating models and using callbacks in Rails. The focus is on data validation before it's saved to the database and triggering actions before or after changes to the Rails objects.

Learning Outcomes

On completing this tutorial, you will be able to:
- Validate data before saving it to the database
- Use callbacks effectively to manage actions on object life cycle events

Prerequisites

  • Basic knowledge of Ruby on Rails
  • Basic understanding of ActiveRecord

Step-by-Step Guide

Models and Validations

In Rails, models are used to interact with the database. It's important to ensure that only valid data gets saved. Rails provides several helper methods to check the validity of data. These validations run before Rails saves data to the database.

For example, you can use validates_presence_of :attribute to ensure that a certain attribute is not empty.

Callbacks

Callbacks are methods that Rails calls at certain moments of an object's life cycle. You can use callbacks to perform logic before or after an object is created, updated, deleted, etc.

For example, before_save :method would run a certain method before the object is saved.

Code Examples

Validations Example

In this example, we have a User model with name, email, and password attributes. We want to ensure no user can be saved without these attributes:

class User < ApplicationRecord
  validates :name, :email, :password, presence: true
end

Here, validates :name, :email, :password, presence: true ensures that these fields must be present before a User object is saved.

Callbacks Example

In the same User model, let's say we want to downcase the email before saving the user:

class User < ApplicationRecord
  validates :name, :email, :password, presence: true
  before_save :downcase_email

  private

  def downcase_email
    self.email = email.downcase
  end
end

Here, before_save :downcase_email is called before the user is saved. The downcase_email method will take the email and convert it to lowercase.

Summary

This tutorial covered:
- Validating models: Ensuring data is valid before saving
- Using callbacks: Triggering actions at certain moments of an object's life cycle

Next, consider exploring other types of validations and callbacks. The Rails Guides are a good resource for this.

Practice Exercises

Exercise 1

Create a Product model with name and price attributes. Ensure that the product cannot be saved without a name and that the price is a positive number.

Exercise 2

In the Product model, create a callback that sets a default price if none is provided.

Exercise 3

Create a before_save callback in the User model that checks if the provided email is in a valid format.

Solutions

Solution to Exercise 1

class Product < ApplicationRecord
  validates :name, presence: true
  validates :price, numericality: { greater_than: 0 }
end

Solution to Exercise 2

class Product < ApplicationRecord
  validates :name, presence: true
  validates :price, numericality: { greater_than: 0 }
  before_save :default_price

  private

  def default_price
    self.price ||= 10
  end
end

Solution to Exercise 3

class User < ApplicationRecord
  validates :name, :email, :password, presence: true
  before_save :downcase_email, :validate_email

  private

  def downcase_email
    self.email = email.downcase
  end

  def validate_email
    unless email =~ URI::MailTo::EMAIL_REGEXP
      errors.add(:email, 'must be a valid email address')
    end
  end
end