ActiveRecord Basics
ActiveRecord is the ORM (Object-Relational Mapping) layer that comes with Ruby on Rails. It lets you interact with your database like you would with Ruby objects — no need to write raw SQL for most operations. In this tutorial, you’ll learn how to create models, perform CRUD operations, define relationships, and build queries with ActiveRecord.
What is ActiveRecord?
ActiveRecord is Rails’ implementation of the ORM pattern. It maps database tables to Ruby classes, and rows to objects. When you create a model in Rails, you get a powerful interface for interacting with your database.
# This automatically maps to a "users" table
class User < ApplicationRecord
end
Each attribute in the database becomes a method on your model:
user = User.find(1)
user.name # => "Alice"
user.email # => "alice@example.com"
Creating Models
Generate a model with the Rails generator:
rails generate model Article title:string body:text published:boolean
This creates:
app/models/article.rb— The model classdb/migrate/20260307123456_create_articles.rb— The migration
The model inherits from ApplicationRecord, which inherits from ActiveRecord::Base:
# app/models/article.rb
class Article < ApplicationRecord
end
CRUD Operations
ActiveRecord provides methods for all standard database operations:
Create
# Create a new article
article = Article.new(title: "Hello World", body: "My first post")
article.save
# Or use create to save in one step
article = Article.create(title: "Second Post", body: "Content here")
Read
# Find by primary key
article = Article.find(1)
# Find first match
article = Article.find_by(title: "Hello World")
# Get all records
articles = Article.all
# Find with conditions
published_articles = Article.where(published: true)
Update
article = Article.find(1)
article.title = "Updated Title"
article.save
# Or update in one step
article.update(title: "New Title", body: "New content")
# Update multiple records
Article.where(published: false).update_all(published: true)
Delete
article = Article.find(1)
article.destroy
# Delete without loading into memory
Article.destroy(1)
Article.destroy_all(published: true)
Validations
ActiveRecord lets you validate data before saving to the database:
class Article < ApplicationRecord
validates :title, presence: true
validates :body, length: { minimum: 10 }
validates :slug, uniqueness: true
end
Common validations:
class User < ApplicationRecord
validates :email, presence: true
validates :email, format: { with: /\A[^@]+@[^@]+\z/ }
validates :age, numericality: { greater_than: 0 }
validates :username, length: { in: 3..20 }
validates :terms, acceptance: true
end
Relationships
ActiveRecord makes defining database relationships simple:
Belongs To
class Article < ApplicationRecord
belongs_to :author
end
Has Many
class Author < ApplicationRecord
has_many :articles
end
Has One
class Profile < ApplicationRecord
belongs_to :user
has_one :avatar
end
Many-to-Many with Join Table
class Article < ApplicationRecord
has_many :taggings
has_many :tags, through: :taggings
end
class Tagging < ApplicationRecord
belongs_to :article
belongs_to :tag
end
class Tag < ApplicationRecord
has_many :taggings
has_many :articles, through: :taggings
end
Query Interface
ActiveRecord provides a powerful chainable query interface:
# Chaining scopes
articles = Article
.where(published: true)
.where("created_at > ?", 1.week.ago)
.order(created_at: :desc)
.limit(10)
Common methods:
# Filtering
Article.where(published: true) # WHERE clause
Article.order(:title) # ORDER BY
Article.limit(5) # LIMIT
Article.offset(10) # OFFSET
Article.select(:title, :body) # SELECT specific columns
Article.distinct # SELECT DISTINCT
# Aggregation
Article.count # COUNT
Article.sum(:view_count) # SUM
Article.average(:rating) # AVG
Article.minimum(:price) # MIN
Article.maximum(:price) # MAX
Scopes
Scopes are reusable query chains defined in your model:
class Article < ApplicationRecord
# Simple scope
scope :published, -> { where(published: true) }
# Scope with arguments
scope :recent, ->(days) { where("created_at > ?", days.days.ago) }
# You can also define as class methods
def self.popular
where("view_count > ?", 1000)
end
end
# Usage
Article.published.recent(7)
Article.popular.where(title: "Hello")
Callbacks
Callbacks let you run code at specific points in the object lifecycle:
class Article < ApplicationRecord
before_validation :set_slug
private
def set_slug
self.slug = title.parameterize if slug.blank?
end
end
Common callbacks:
before_validation/after_validationbefore_save/around_save/after_savebefore_create/around_create/after_createbefore_update/around_update/after_updatebefore_destroy/around_destroy/after_destroy
Migrations
Migrations manage your database schema over time:
# Create a migration
rails generate migration AddPublishedAtToArticles published_at:datetime
# Run migrations
rails db:migrate
# Rollback
rails db:rollback
Common migration operations:
class CreateArticles < ActiveRecord::Migration[7.1]
def change
create_table :articles do |t|
t.string :title
t.text :body
t.boolean :published, default: false
t.timestamps
end
end
end
Example: Complete Article Model
Here’s a more complete example bringing together what you’ve learned:
class Article < ApplicationRecord
# Relationships
belongs_to :author
has_many :comments, dependent: :destroy
has_many :taggings, dependent: :destroy
has_many :tags, through: :taggings
# Validations
validates :title, presence: true, length: { minimum: 5 }
validates :body, presence: true
validates :slug, uniqueness: true
# Scopes
scope :published, -> { where(published: true) }
scope :drafts, -> { where(published: false) }
scope :recent, -> { order(created_at: :desc) }
# Callbacks
before_validation :generate_slug
private
def generate_slug
self.slug = title.parameterize if slug.blank?
end
end
Common Pitfalls
Watch out for these common issues:
# BAD: N+1 query problem
articles = Article.all
articles.each do |article|
puts article.author.name # Each access triggers a query!
end
# GOOD: Eager loading
articles = Article.includes(:author).all
articles.each do |article|
puts article.author.name # Authors loaded in one query
end
# BAD: Using update_column (bypasses validations)
article.update_column(:published, true)
# GOOD: Use update (runs validations)
article.update(published: true)
Summary
ActiveRecord is the heart of data handling in Rails:
- Models map to database tables
- CRUD operations are simple method calls
- Validations ensure data integrity
- Relationships connect models elegantly
- Query Interface builds SQL chains in Ruby
- Scopes create reusable queries
- Callbacks hook into the object lifecycle
Master ActiveRecord and you’ll be able to build data-driven Rails applications efficiently without touching raw SQL.
In the next tutorial, we’ll explore Rails routing and see how HTTP requests are mapped to controller actions.