Associations
has_many and belongs_to.
Associations is a free Ruby Academy lesson on CoddyKit. This is lesson 3 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the Ruby Academy learning path, and your progress syncs across the web and the CoddyKit app. The Ruby Academy course includes 4 lessons in total.
What Are Associations?
Associations declare relationships between models so Active Record can navigate related rows for you. Instead of writing join SQL, you call methods like user.posts.
- They mirror the foreign keys in your database.
- They generate helper methods automatically.
- They make code read like the domain.
belongs_to
belongs_to says this model holds a foreign key pointing to another. A Comment that belongs to a Post has a post_id column.
class Comment < ApplicationRecord
belongs_to :post
end
# comment.post returns the parent Post
# Requires a post_id column on commentshas_many
has_many is the other side: one record owns many of another. A Post has many Comment records. The foreign key lives on the many side.
class Post < ApplicationRecord
has_many :comments
end
# post.comments returns all related comments
# post.comments.create(body: "Nice!")Where the Foreign Key Lives
The model that belongs_to holds the foreign key. For Post and Comment, the comments table has post_id. Set this up in a migration with t.references :post or add_reference.
create_table :comments do |t|
t.references :post, foreign_key: true
t.text :body
t.timestamps
endGenerated Methods
A has_many :comments gives you a collection with handy methods:
post.commentsto read.post.comments.create(...)to add a linked record.post.comments.countto count.post.comment_idsfor the ids.
post = Post.find(1)
post.comments.create(body: "First!")
puts post.comments.counthas_one
has_one models a one-to-one link, like a User that has one Profile. The foreign key still lives on the other model (profiles.user_id).
class User < ApplicationRecord
has_one :profile
end
class Profile < ApplicationRecord
belongs_to :user
endMany-to-Many with through
For many-to-many, use a join model and has_many through. A Student has many Course records through Enrollment rows.
class Student < ApplicationRecord
has_many :enrollments
has_many :courses, through: :enrollments
end
class Enrollment < ApplicationRecord
belongs_to :student
belongs_to :course
endDependent Options
Decide what happens to children when a parent is deleted with dependent:
dependent: :destroydeletes children too.dependent: :nullifyclears their foreign key.dependent: :restrict_with_errorblocks deletion.
class Post < ApplicationRecord
has_many :comments, dependent: :destroy
endThe N+1 Query Problem
Looping over records and touching an association can fire one query per record, the dreaded N+1. Loading 10 posts then their comments can run 11 queries instead of 2.
This silently slows applications as data grows.
# N+1: one query per post for comments
Post.all.each do |post|
puts post.comments.count
endFixing N+1 with includes
includes tells Active Record to eager-load the association in a couple of queries instead of many. This is the standard fix for N+1.
Post.includes(:comments).each do |post|
puts post.comments.count
endCustom Names with class_name
When the association name does not match the model, use options like class_name and foreign_key. For example an author association backed by the User model.
class Post < ApplicationRecord
belongs_to :author, class_name: "User"
endQuick Check
Test your understanding of associations.
Recap: Associations
You learned how to relate models:
belongs_toholds the foreign key;has_manyandhas_oneare the other side.has_many throughmodels many-to-many.dependentcontrols cascading deletes.- Avoid N+1 queries with
includes.
Next we ensure data integrity with validations and learn to query.
Learn Ruby with an AI tutor — free
Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.
- Courses
- 29
- Lessons
- 109
Frequently Asked Questions
Is the “Associations” lesson free?
Yes — any 3 lessons of the Ruby Academy learning path, including “Associations”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The Ruby Academy course includes 4 lessons in total.
What will I learn in “Associations”?
has_many and belongs_to. You practise Ruby Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Ruby Academy?
No prior experience is required. Ruby Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 3 of 4.
How long does the “Associations” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Ruby Academy lesson?
Yes. Every Ruby Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.