Rails associations: belongs_to, has_one, has_many explained

The key idea is:

belongs_to tells Rails where the foreign key lives.
has_one / has_many tells Rails how the other side relates to that row.

Let’s build this from SQL upward.

1. Start with the database

Suppose we have:

users
-----
id
name
profiles
--------
id
bio
user_id

The important column is:

profiles.user_id

That foreign key says:

“This profile belongs to this user.”

So in Rails:

class Profile < ApplicationRecord
belongs_to :user
end
class User < ApplicationRecord
has_one :profile
end

The database relationship looks like:

users
id = 1
|
| user_id = 1
v
profiles

SQL

If you have:

users
1 | Abhilash

and:

profiles
10 | Senior Engineer | 1

then:

profiles.user_id = users.id

Rails uses that to find the relationship.

For:

profile.user

Rails effectively does:

SELECT *
FROM users
WHERE users.id = 1
LIMIT 1;

For:

user.profile

Rails effectively does:

SELECT *
FROM profiles
WHERE profiles.user_id = 1
LIMIT 1;

The important thing is that the foreign key is on profiles.


2. What does belongs_to actually mean?

Consider:

class Profile < ApplicationRecord
belongs_to :user
end

This means:

A Profile record belongs to a User record.

Rails expects a foreign key on the profiles table:

profiles
---------
id
bio
user_id <-- FK

So:

profile.user

means:

profile.user_id -> users.id

Mental model

Think:

belongs_to
|
v
"I have the foreign key"

That is the most useful rule to remember.


3. What does has_one mean?

Now:

class User < ApplicationRecord
has_one :profile
end

This means:

A User has one Profile.

But notice something important.

There is no profile_id in users.

Instead, the foreign key remains here:

profiles
---------
id
user_id <-- FK

So:

user.profile

means:

SELECT *
FROM profiles
WHERE profiles.user_id = 1
LIMIT 1;

Therefore:

class User < ApplicationRecord
has_one :profile
end

does not mean the users table contains a profile_id.


4. So why do we need both?

Because each association describes the relationship from a different direction.

class User < ApplicationRecord
has_one :profile
end
class Profile < ApplicationRecord
belongs_to :user
end

These are the two sides of the same relationship.

User
|
| has_one
v
Profile
|
| belongs_to
v
User

And the database has:

users
-----
id
profiles
--------
id
user_id <-- foreign key

So yes:

If one model has belongs_to, the other model does not automatically mean has_one.

It could be either has_one or has_many.

That’s the really important part.


5. belongs_to + has_many

Suppose one company has many employees.

Database:

companies
---------
id
name
employees
---------
id
name
company_id

Here:

employees.company_id -> companies.id

Rails:

class Employee < ApplicationRecord
belongs_to :company
end
class Company < ApplicationRecord
has_many :employees
end

Now:

employee.company

finds one company:

SELECT *
FROM companies
WHERE companies.id = employees.company_id
LIMIT 1;

But:

company.employees

finds multiple employees:

SELECT *
FROM employees
WHERE employees.company_id = 1;

Example data:

companies
id | name
---+---------
1 | Acme
employees
id | name | company_id
---+------------+-----------
10 | Alice | 1
11 | Bob | 1
12 | Charlie | 1

So:

employee.company

returns one object:

#<Company id: 1>

while:

company.employees

returns a collection:

[
#<Employee id: 10>,
#<Employee id: 11>,
#<Employee id: 12>
]

6. The foreign key determines the structure

This is the easiest way to understand Rails associations.

Suppose:

employees.company_id

exists.

Then:

Employee belongs_to Company

because Employee holds the foreign key.

But what does Company have?

It depends on the business rule.

Case A: One company can have many employees

class Company
has_many :employees
end

Case B: One company can have only one employee

class Company
has_one :employee
end

The database column is still:

employees.company_id

The difference is the cardinality/business rule.


7. belongs_to does NOT tell you whether the other side is has_one or has_many

This is a very common misunderstanding.

Suppose:

class Employee
belongs_to :company
end

You cannot automatically conclude:

class Company
has_one :employee
end

It might be:

class Company
has_many :employees
end

Think of it like this

Employee
|
| belongs_to
v
Company

The question is:

How many employees can belong to the same company?

If:

1 employee -> 1 company
1 company -> many employees

then:

Employee belongs_to Company
Company has_many Employees

If:

1 employee -> 1 company
1 company -> 1 employee

then:

Employee belongs_to Company
Company has_one Employee

8. SQL makes this much clearer

Let’s compare the two.

has_one

users
-----
id
profiles
--------
id
user_id

Rails:

class User
has_one :profile
end
class Profile
belongs_to :user
end

SQL:

SELECT *
FROM profiles
WHERE profiles.user_id = 1
LIMIT 1;

The LIMIT 1 reflects the expectation that the relationship is singular.

But here’s an important detail:

Rails association declaration alone does not enforce uniqueness at the database level.

If you really mean one profile per user, add a unique index:

add_index :profiles, :user_id, unique: true

Then the database guarantees:

user_id = 1

cannot appear twice.


9. has_many

Same database structure:

users
-----
id
posts
-----
id
title
user_id

Rails:

class User
has_many :posts
end
class Post
belongs_to :user
end

SQL:

SELECT *
FROM posts
WHERE posts.user_id = 1;

Now the database can have:

posts
id | title | user_id
---+----------------+---------
1 | Hello Rails | 1
2 | ActiveRecord | 1
3 | PostgreSQL | 1

So:

user.posts

returns three records.


10. What about belongs_to on both sides?

You technically could write:

class A
belongs_to :b
end
class B
belongs_to :a
end

but then Rails expects:

a.b_id
b.a_id

That’s usually a different database design, not the normal one-to-one association.

For a standard one-to-one relationship, normally you want:

A has_one B
B belongs_to A

with one foreign key:

b.a_id

11. A practical way to design associations

When designing a relationship, start with the database.

Example: User and Address

Ask:

Can a user have multiple addresses?

If yes:

class User
has_many :addresses
end
class Address
belongs_to :user
end

Database:

addresses
---------
id
user_id
street
city

If each user can have only one address:

class User
has_one :address
end
class Address
belongs_to :user
end

Same foreign key:

addresses.user_id

But now enforce the one-to-one invariant:

add_index :addresses, :user_id, unique: true

15. The simplest mental model

Memorize this:

belongs_to = "I contain the foreign key"
has_one = "The other table contains my foreign key,
and there should be one matching record"
has_many = "The other table contains my foreign key,
and there can be many matching records"

For example:

           user_id
users <---------------- profiles
  1                       1
  |                       |
  | has_one               | belongs_to
  |                       |
  +-----------------------+

And:

           user_id
users <---------------- posts
  1                      many
  |                       |
  | has_many              | belongs_to
  |                       |
  +-----------------------+

The one rule I would use in an interview

When someone asks:

“How do you decide between has_one and has_many?”

Answer:

“First I locate the foreign key. The model containing the foreign key uses belongs_to. On the parent side, I choose has_one or has_many based on the cardinality of the relationship. For a true one-to-one relationship, I also enforce uniqueness of the foreign key at the database level.”

That answer demonstrates that you understand Rails associations as a database relationship, rather than just memorizing Rails syntax.