Understanding Active Record Associations

In Ruby on Rails, associating models is quite trivial but does come with some conventions you will need to be familiar with as you build progressive web apps with the framework. This post is my attempt to get you to understand Active Record Associations within the Ruby on Rails framework.

Consider this walk-through a quick overview of the associations you might make use of in a rails application. These associations are a convenient way to get data to relate all the way down to the database layer. Every relationship happens within the model layer of the rails app. You can extend associations even further if need be depending on your own apps needs.


# belongs_to

# app/models/book.rb
class Book < ApplicationRecord
  belongs_to :author

  # must be singular
  # Sets up a 1:1 connection with another model - Author in this case
  # Books associated to author via `author_id` on books table


# has_many

# app/models/author.rb
class Author < ApplicationRecord
  has_many :books

  # naming is plural
  # indicates a one-to-many association
  # an author can have many books in this example
  # books associated via `author_id`


# has_one

class Supplier < ApplicationRecord
  has_one :account

  # only contains one instance of another model
  # Supplier will only ever have a single account in this example
  # Account associate via `supplier_id`

has_many through

# has_many :through

# sets up a many-to-many association using another model

# app/models/physician.rb
class Physician < ApplicationRecord
  has_many :appointments
  has_many :patients, through: :appointments

# app/models/appoinment.rb
# the appointments table would have both a `physician_id` and `patient_id` column
class Appointment < ApplicationRecord
  belongs_to :physician
  belongs_to :patient

# app/models/patient.rb
class Patient < ApplicationRecord
  has_many :appointments
  has_many :physicians, through: :appointments

has_one through

# has one through

# sets up a one-to-one connection with another model but can proceed through a third model

# app/models/supplier.rb

class Supplier < ApplicationRecord
  has_one :account
  has_one :account_history, through: :account

# app/models/account.rb

# suppliers reference `supplier_id`
class Account < ApplicationRecord
  belongs_to :supplier
  has_one :account_history

# app/models/account_history.rb

# account_histores referenced by `account_id`
class AccountHistory < ApplicationRecord
  belongs_to :account

Has and belongs to many

# Has and Belongs to many (has_and_belongs_to_many - HABTM)

# A direct many-to-many connection with another model without a third intervening model. You'll need to create a simple join table to use this type of association. It's limiting in terms of advanced querying so use with caution.

# The naming convention of the join table would take the name of both models and become plural so

# assemblies_parts is the new table name which contains an `assembly_id` and `part_id` only.

# app/models/assembly.rb
class Assembly < ApplicationRecord
  has_and_belongs_to_many :parts

# app/models/part.rb
class Part < ApplicationRecord
  has_and_belongs_to_many :assemblies


# polymorphic
# With polymorphic associations, a model can belong to more than one other model, on a single association.

# app/models/picture.rb
# pictures table has both `imageable_id`, and `imageable_type`
class Picture < ApplicationRecord
  belongs_to :imageable, polymorphic: true

# app/models/employee.rb
class Employee < ApplicationRecord
  has_many :pictures, as: :imageable

# app/models/product.rb
class Product < ApplicationRecord
  has_many :pictures, as: :imageable

Shameless plug time

I have a new course called Hello Rails. Hello Rails is modern course designed to help you start using and understanding Ruby on Rails fast. If you’re a novice when it comes to Ruby or Ruby on Rails I invite you to check out the site. The course will be much like these builds but a super more in-depth version with more realistic goals and deliverables. Sign up to get notified today!

Follow @hello_rails and myself @justalever on Twitter.