📖 Scenario: You are building a simple library system where books can have many authors, and authors can write many books. You will use Rails associations to connect Book and Author models through a join model called Authorship.
🎯 Goal: Create a many-to-many relationship between Book and Author models using has_many :through association with the join model Authorship.
📋 What You'll Learn
Create a Book model with a title attribute
Create an Author model with a name attribute
Create an Authorship join model with book_id and author_id as foreign keys
Set up has_many :through associations in Book and Author models
Set up belongs_to associations in Authorship model
💡 Why This Matters
🌍 Real World
Many real-world apps need to connect two things that can have many links between them, like books and authors, students and courses, or users and roles.
💼 Career
Understanding has_many :through associations is essential for Rails developers to model complex data relationships cleanly and maintainably.
Progress0 / 4 steps
1
Create the initial models
Create three Rails models: Book with attribute title:string, Author with attribute name:string, and Authorship with attributes book_id:integer and author_id:integer.
Ruby on Rails
Hint
Use rails generate model commands or create model files with the specified attributes.
2
Add belongs_to associations in Authorship
In the Authorship model, add belongs_to :book and belongs_to :author associations.
Ruby on Rails
Hint
Each Authorship belongs to one Book and one Author.
3
Add has_many through associations in Book and Author
In the Book model, add has_many :authorships and has_many :authors, through: :authorships. In the Author model, add has_many :authorships and has_many :books, through: :authorships.
Ruby on Rails
Hint
Use has_many :through to connect Book and Author through Authorship.
4
Complete the association setup
Ensure all models have the correct associations: Book and Author have has_many :authorships and has_many :through associations, and Authorship has belongs_to associations.
Ruby on Rails
Hint
Double-check all associations are correctly set for the many-to-many relationship.
Practice
(1/5)
1. What is the main purpose of using has_many :through in Rails models?
easy
A. To create a many-to-many relationship using a join model
B. To create a one-to-one relationship between two models
C. To validate data before saving to the database
D. To automatically generate database migrations
Solution
Step 1: Understand relationship types in Rails
Rails uses associations to connect models. has_many :through is specifically for many-to-many relationships.
Step 2: Identify the role of join models
It uses a join model to connect two other models, allowing extra data on the connection.
Final Answer:
To create a many-to-many relationship using a join model -> Option A
Quick Check:
has_many :through = many-to-many with join model [OK]
Hint: Think: many-to-many needs a join model [OK]
Common Mistakes:
Confusing has_many :through with has_one
Thinking it automatically creates migrations
Using it for one-to-one relationships
2. Which of the following is the correct way to declare a many-to-many association using has_many :through in the Author model?
easy
A. has_one :books, through: :authorships
B. has_many :books, through: :authorships
C. belongs_to :books, through: :authorships
D. has_many :authorships, through: :books
Solution
Step 1: Identify the correct association syntax
The model that wants to access the other through a join model uses has_many :other_model, through: :join_model.
Step 2: Apply to Author model
Author has many books through authorships, so has_many :books, through: :authorships is correct.
Final Answer:
has_many :books, through: :authorships -> Option B
class Author < ApplicationRecord
has_many :authorships
has_many :books, through: :authorships
end
class Authorship < ApplicationRecord
belongs_to :author
belongs_to :book
end
class Book < ApplicationRecord
has_many :authorships
has_many :authors, through: :authorships
end
What will Author.first.books.count return if the first author has 3 books linked through authorships?
medium
A. 1
B. 0
C. 3
D. An error because of missing join table
Solution
Step 1: Understand the association setup
Author has many books through authorships, so calling Author.first.books fetches all books linked via authorships.
Step 2: Count the linked books
If the first author has 3 books linked, Author.first.books.count returns 3.
Final Answer:
3 -> Option C
Quick Check:
Author.first.books.count = number of linked books [OK]
Hint: Count returns linked records through join model [OK]
Common Mistakes:
Assuming count returns authorships count
Expecting zero without checking data
Confusing belongs_to with has_many effects
4. You have these models:
class Student < ApplicationRecord
has_many :enrollments
end
class Enrollment < ApplicationRecord
belongs_to :student
belongs_to :course
end
class Course < ApplicationRecord
has_many :enrollments
has_many :students, through: :enrollments
end
But when you run Student.first.courses, you get an error: undefined method 'courses'. What is the likely cause?
medium
A. The has_many :courses, through: :enrollments line is missing in Student model
B. The Enrollment model is missing belongs_to :course
C. The Course model should use belongs_to :student instead of has_many
D. The database table for enrollments does not exist
Solution
Step 1: Check Student model associations
The error says courses method is undefined, meaning Student model lacks has_many :courses, through: :enrollments.
Step 2: Confirm other associations
Enrollment and Course models are correct; missing association in Student causes the error.
Final Answer:
The has_many :courses, through: :enrollments line is missing in Student model -> Option A
Quick Check:
Missing has_many through causes undefined method [OK]
Hint: Check if has_many :through is declared in the model [OK]
5. You want to track the date when a User joins a Group using a many-to-many relationship with has_many :through. Which setup correctly allows storing this extra data?
hard
A. Add joined_on column directly to users table and use has_many :groups
B. Store joined_on in a separate table unrelated to the join
C. Use has_and_belongs_to_many :groups without a join model
D. Create a join model Membership with user_id, group_id, and joined_on columns, then use has_many :groups, through: :memberships in User
Solution
Step 1: Understand storing extra data in many-to-many
Extra data on the connection requires a join model with its own columns.
Step 2: Apply to User and Group
Create a join model Membership with user_id, group_id, and joined_on columns. Then User uses has_many :groups, through: :memberships.
Final Answer:
Create a join model Membership with user_id, group_id, and joined_on columns, then use has_many :groups, through: :memberships in User -> Option D
Quick Check:
Extra data needs join model with columns [OK]
Hint: Use join model to store extra data in many-to-many [OK]
Common Mistakes:
Adding extra columns to main models instead of join model
Using has_and_belongs_to_many which lacks extra data support
Storing extra data in unrelated tables
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.