# Relationships
Introduction
Database tables are often related to one another. For example, a blog post may have many comments or an order could be related to the user who placed it. Active Record makes managing and working with these relationships easy, and supports a variety of common relationships:
- One To One
- One To Many
- Many To Many
- Has One Through
- Has Many Through
- One To One (Polymorphic)
- One To Many (Polymorphic)
- Many To Many (Polymorphic)
Relations
One to One
A one-to-one relationship is a very basic type of database relationship. For example, a
User
model might be associated with one **Phone
**model. To define this relationship, we will place ahas_one
phone on the **User
**model.class User < ApplicationRecord has_one :phone end
1
2
3class Phone < ApplicationRecord validates_uniqueness_of :user_id, message: "can not have more than one phone" end
1
2
3The corresponding migration might look like this:
class CreateUsers < ActiveRecord::Migration[7.0] def change create_table :users do |t| t.string :name t.timestamps end create_table :phones do |t| t.belongs_to :user t.string :phone_number t.timestamps end end end
1
2
3
4
5
6
7
8
9
10
11
12
13
14Depending on the use case, you might also need to create a unique index and/or a foreign key constraint on the supplier column for the accounts table. In this case, the column definition might look like this:
create_table :phones do |t| t.belongs_to :user, index: { unique: true }, foreign_key: true # ... end
1
2
3
4In order to link the resource , you can do by
Phone.create({user: User.find(1) , phone_number:'9823432543'}) #You can also provide id direct Phone.create({user_id: 1 , phone_number:'9823432543'})
1
2
3
4You can access the associated relation by
phone = User.find(1).phone
1Defining inverse of relation:
So, we can access the **
Phone
**model from our **User
**model. Next, let's define a relationship on the **Phone
**model that will let us access the user that owns the phone. We can define the inverse of a **has_one
**relationship using thebelongs_to
method:class Phone < ApplicationRecord belongs_to :user end
1
2
3One to Many
A one-to-many relationship is used to define relationships where a single model is the parent to one or more child models. For example, a blog post may have an infinite number of comments. Like all other Active record relationships, one-to-many relationships are defined by defining a method on your Active record model:
class Post < ApplicationRecord has_many :comments end
1
2
3The corresponding migration might look like this:
class CreatePosts < ActiveRecord::Migration[7.0] def change create_table :posts do |t| t.string :title t.timestamps end create_table :comments do |t| t.belongs_to :post t.datetime :published_at t.timestamps end end end
1
2
3
4
5
6
7
8
9
10
11
12
13
14Depending on the use case, it's usually a good idea to create a non-unique index and optionally a foreign key constraint on the author column for the books table:
create_table :comments do |t| t.belongs_to :post, index: true, foreign_key: true # ... end
1
2
3
4You can access the associated relation by
comments = Post.find(1).comments
1Has One Through
A
[has_one :through](https://api.rubyonrails.org/v7.0.4/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_one)
association sets up a one-to-one connection with another model. This association indicates that the declaring model can be matched with one instance of another model by proceeding through a third model. For example, if each supplier has one account, and each account is associated with one account history, then the supplier model could look like this:class Supplier < ApplicationRecord has_one :account has_one :account_history, through: :account end class Account < ApplicationRecord belongs_to :supplier has_one :account_history end class AccountHistory < ApplicationRecord belongs_to :account end
1
2
3
4
5
6
7
8
9
10
11
12
13The corresponding migration might look like this:
class CreateAccountHistories < ActiveRecord::Migration[7.0] def change create_table :suppliers do |t| t.string :name t.timestamps end create_table :accounts do |t| t.belongs_to :supplier t.string :account_number t.timestamps end create_table :account_histories do |t| t.belongs_to :account t.integer :credit_rating t.timestamps end end end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Many to Many
Has Many Through
A
[has_many :through](https://api.rubyonrails.org/v7.0.4/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many)
association is often used to set up a many-to-many connection with another model. This association indicates that the declaring model can be matched with zero or more instances of another model by proceeding through a third model. For example, consider a medical practice where patients make appointments to see physicians. The relevant association declarations could look like this:class Physician < ApplicationRecord has_many :appointments has_many :patients, through: :appointments end class Appointment < ApplicationRecord belongs_to :physician belongs_to :patient end class Patient < ApplicationRecord has_many :appointments has_many :physicians, through: :appointments end
1
2
3
4
5
6
7
8
9
10
11
12
13
14The corresponding migration might look like this:
class CreateAppointments < ActiveRecord::Migration[7.0] def change create_table :physicians do |t| t.string :name t.timestamps end create_table :patients do |t| t.string :name t.timestamps end create_table :appointments do |t| t.belongs_to :physician t.belongs_to :patient t.datetime :appointment_date t.timestamps end end end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20The collection of join models can be managed via the
[has_many
association methods](https://guides.rubyonrails.org/association_basics.html#has-many-association-reference) . For example, if you assign:physician.patients = patients
1Then new join models are automatically created for the newly associated objects. If some that existed previously are now missing, then their join rows are automatically deleted.
has and belongs to many
A
[has_and_belongs_to_many](https://api.rubyonrails.org/v7.0.4/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_and_belongs_to_many)
association creates a direct many-to-many connection with another model, with no intervening model. This association indicates that each instance of the declaring model refers to zero or more instances of another model. For example, if your application includes assemblies and parts, with each assembly having many parts and each part appearing in many assemblies, you could declare the models this way:class Assembly < ApplicationRecord has_and_belongs_to_many :parts end class Part < ApplicationRecord has_and_belongs_to_many :assemblies end
1
2
3
4
5
6
7The corresponding migration might look like this:
class CreateAssembliesAndParts < ActiveRecord::Migration[7.0] def change create_table :assemblies do |t| t.string :name t.timestamps end create_table :parts do |t| t.string :part_number t.timestamps end create_table :assemblies_parts, id: false do |t| t.belongs_to :assembly t.belongs_to :part end end end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Polymorphic Relationships
A slightly more advanced twist on associations is the polymorphic association. With polymorphic associations, a model can belong to more than one other model, on a single association. For example, you might have a picture model that belongs to either an employee model or a product model. Here's how this could be declared:
class Picture < ApplicationRecord belongs_to :imageable, polymorphic: true end class Employee < ApplicationRecord has_many :pictures, as: :imageable end class Product < ApplicationRecord has_many :pictures, as: :imageable end
1
2
3
4
5
6
7
8
9
10
11You can think of a polymorphic
belongs_to
declaration as setting up an interface that any other model can use. From an instance of theEmployee
model, you can retrieve a collection of pictures:@employee.pictures
.Similarly, you can retrieve
@product.pictures
.If you have an instance of the
Picture
model, you can get to its parent via@picture.imageable
. To make this work, you need to declare both a foreign key column and a type column in the model that declares the polymorphic interface:class CreatePictures < ActiveRecord::Migration[7.0] def change create_table :pictures do |t| t.string :name t.bigint :imageable_id t.string :imageable_type t.timestamps end add_index :pictures, [:imageable_type, :imageable_id] end end
1
2
3
4
5
6
7
8
9
10
11
12This migration can be simplified by using the
t.references
form:class CreatePictures < ActiveRecord::Migration[7.0] def change create_table :pictures do |t| t.string :name t.references :imageable, polymorphic: true t.timestamps end end end
1
2
3
4
5
6
7
8
9Self Joins
In designing a data model, you will sometimes find a model that should have a relation to itself. For example, you may want to store all employees in a single database model, but be able to trace relationships such as between manager and subordinates. This situation can be modeled with self-joining associations:
class Employee < ApplicationRecord has_many :subordinates, class_name: "Employee", foreign_key: "manager_id" belongs_to :manager, class_name: "Employee", optional: true end
1
2
3
4
5
6With this setup, you can retrieve
@employee.subordinates
and@employee.manager
.In your migrations/schema, you will add a references column to the model itself.
class CreateEmployees < ActiveRecord::Migration[7.0] def change create_table :employees do |t| t.references :manager, foreign_key: { to_table: :employees } t.timestamps end end end
1
2
3
4
5
6
7
8
← Validation Callbacks →