0
0
RailsHow-ToBeginner · 4 min read

How to Use has_many through in Rails: Simple Guide

In Rails, has_many :through sets up a many-to-many connection with another model through a third join model. It allows you to work with the associated records directly while keeping the join model for extra data or logic.
📐

Syntax

The has_many :through association connects two models through a third join model. You declare has_many on both sides and specify the join model with through:.

Example parts:

  • has_many :join_models: links to the join table model.
  • has_many :associated_models, through: :join_models: links to the final associated model through the join model.
ruby
class ModelA < ApplicationRecord
  has_many :join_models
  has_many :model_bs, through: :join_models
end

class JoinModel < ApplicationRecord
  belongs_to :model_a
  belongs_to :model_b
end

class ModelB < ApplicationRecord
  has_many :join_models
  has_many :model_as, through: :join_models
end
💻

Example

This example shows Doctors and Patients connected through Appointments. Doctors have many patients through appointments, and patients have many doctors through appointments.

ruby
class Doctor < ApplicationRecord
  has_many :appointments
  has_many :patients, through: :appointments
end

class Appointment < ApplicationRecord
  belongs_to :doctor
  belongs_to :patient
end

class Patient < ApplicationRecord
  has_many :appointments
  has_many :doctors, through: :appointments
end

# Usage in Rails console:
doctor = Doctor.create(name: "Dr. Smith")
patient = Patient.create(name: "John Doe")
appointment = Appointment.create(doctor: doctor, patient: patient)

# Access patients of doctor
puts doctor.patients.pluck(:name) # => ["John Doe"]

# Access doctors of patient
puts patient.doctors.pluck(:name) # => ["Dr. Smith"]
Output
["John Doe"] ["Dr. Smith"]
⚠️

Common Pitfalls

Common mistakes when using has_many :through include:

  • Not defining the join model with belongs_to associations properly.
  • Using has_and_belongs_to_many when you need extra data on the join model.
  • Forgetting to create the join model's database table.
  • Trying to use through without the intermediate association.

Always ensure the join model exists and has foreign keys to both associated models.

ruby
class Doctor < ApplicationRecord
  # Wrong: missing join model association
  # has_many :patients, through: :appointments

  # Right:
  has_many :appointments
  has_many :patients, through: :appointments
end

class Appointment < ApplicationRecord
  # Must have both belongs_to
  belongs_to :doctor
  belongs_to :patient
end
📊

Quick Reference

Tips for using has_many :through:

  • Use when you need to store extra info on the join model.
  • Always define belongs_to in the join model for both sides.
  • Access associated records directly through the has_many :through association.
  • Use migrations to create join tables with foreign keys.

Key Takeaways

Use has_many :through to connect models via a join model with extra data or logic.
Define belongs_to associations in the join model for both connected models.
Access associated records directly through the has_many :through association.
Ensure the join model and its database table exist with proper foreign keys.
Avoid has_and_belongs_to_many if you need to store extra information on the join.