Validations in Ruby on Rails
ActiveRecord rules that enforce data integrity by checking model attributes before they are saved to the database.
Table of Contents
What Are Validations?
Validations are rules defined on an ActiveRecord model that check whether an object’s attributes are valid before the object is saved to the database. If any rule fails, Rails refuses to persist the record and attaches error messages to the object instead.
Rails ships with a rich set of built-in validation helpers, and developers can also write custom validations for business-specific rules. Validations run at the model level, so they apply no matter where the record is created from: a controller, a console, a background job, or a seed file.
Why Are Validations Useful?
Without validations, invalid or inconsistent data can reach the database, leading to:
-
Blank or malformed records (e.g., users without email addresses)
-
Duplicate entries that should be unique
-
Broken business rules (e.g., negative prices or end dates before start dates)
-
Bugs that are hard to trace because bad data surfaces far from where it was created
Validations help by:
-
Keeping data accurate and consistent at the application level
-
Centralizing rules in the model, so they are defined once and reused everywhere
-
Providing human-readable error messages that can be shown directly in forms
-
Supporting conditional and contextual rules for different workflows
-
Reducing the need for defensive checks scattered across controllers and views
How Do Validations Work?
Validations are triggered automatically when you call methods such as save,create, or update. Rails runs all declared validations first. If any fail, the method returns false (or raises an exception when using the bang versions like save! or create!), and the record is not saved.
Key concepts:
Built-in helpers– Common rules ready to use, such as presence, uniqueness, length, format, numericality, inclusion, exclusion, acceptance, and confirmation.
The errors object – After validation runs, failures are collected in record.errors, which can be inspected or displayed to users.
valid? and invalid? – Methods that run validations without saving, useful for checking a record’s state.
Conditional validations – Options like if:, unless:, and on: that control when a validation runs (for example, only on :create).
Custom validations – Use validate with a custom method, or build a reusable validator class, for rules that built-in helpers cannot express.
Database constraints – Validations are not a substitute for database-level constraints. Rules like uniqueness should be backed by a unique index, since validations alone cannot prevent race conditions.
Skipped validations – Some methods bypass validations, such as update_column, update_all, insert_all, and save(validate: false), so they should be used with care.
Examples
Scenario 1: Basic Validations on a Model
# app/models/user.rb class User < ApplicationRecord validates :name, presence: true validates :email, presence: true, uniqueness: true validates :age, numericality: { greater_than_or_equal_to: 18 } end
This ensures every user has a name, a unique email, and an age of at least 18.
Scenario 2: Format and Length Validations
class User < ApplicationRecord validates :email, format: { with: URI::MailTo::EMAIL_REGEXP } validates :username, length: { minimum: 3, maximum: 20 } end
This checks that the email looks valid and the username falls within an allowed length.
Scenario 3: Conditional Validation
class Order < ApplicationRecord validates :shipping_address, presence: true, if: :physical_product? validates :terms, acceptance: true, on: :create end
The address is required only for physical products, and terms must be accepted only when the order is first created.
Scenario 4: Custom Validation Method
class Event < ApplicationRecord validate :end_date_after_start_date private def end_date_after_start_date return if end_date.blank? || start_date.blank? errors.add(:end_date, "must be after the start date") if end_date < start_date end end
Custom methods handle business rules that built-in helpers cannot express.
Scenario 5: Checking Validity and Reading Errors
user = User.new(email: "") user.valid? # => false user.errors.full_messages # => ["Name can't be blank", "Email can't be blank"]
The error object holds every failure, ready to display in a form or return from an API.
Scenario 6: Backing Uniqueness with a Database Index
# db/migrate/xxxx_add_unique_index_to_users_email.rb add_index :users, :email, unique: true
This prevents duplicate emails even when two requests arrive at the same moment.
Where Are Validations Used?
-
User registration and profile forms (email, password, and name checks)
-
E-commerce apps validating prices, quantities, and stock levels
-
Booking and scheduling systems enforcing date and availability rules
-
APIs that need to return clear error messages for invalid payloads
-
Multi-step workflows where rules change depending on the record’s state
-
Any model where data quality directly affects business outcomes
In Summary
Validations are ActiveRecord’s first line of defense for data integrity. By declaring rules directly on the model, Rails ensures that only valid records are saved, while giving users and developers clear feedback when something is wrong. For critical rules like uniqueness, pair validations with database constraints for complete protection.