The key idea is:
belongs_totells Rails where the foreign key lives.has_one/has_manytells 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-----idnameprofiles--------idbiouser_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 :userendclass User < ApplicationRecord has_one :profileend
The database relationship looks like:
users id = 1 | | user_id = 1 vprofiles
SQL
If you have:
users1 | Abhilash
and:
profiles10 | Senior Engineer | 1
then:
profiles.user_id = users.id
Rails uses that to find the relationship.
For:
profile.user
Rails effectively does:
SELECT *FROM usersWHERE users.id = 1LIMIT 1;
For:
user.profile
Rails effectively does:
SELECT *FROM profilesWHERE profiles.user_id = 1LIMIT 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 :userend
This means:
A
Profilerecord belongs to aUserrecord.
Rails expects a foreign key on the profiles table:
profiles---------idbiouser_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 :profileend
This means:
A
Userhas oneProfile.
But notice something important.
There is no profile_id in users.
Instead, the foreign key remains here:
profiles---------iduser_id <-- FK
So:
user.profile
means:
SELECT *FROM profilesWHERE profiles.user_id = 1LIMIT 1;
Therefore:
class User < ApplicationRecord has_one :profileend
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 :profileendclass Profile < ApplicationRecord belongs_to :userend
These are the two sides of the same relationship.
User | | has_one vProfile | | belongs_to vUser
And the database has:
users-----idprofiles--------iduser_id <-- foreign key
So yes:
If one model has
belongs_to, the other model does not automatically meanhas_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---------idnameemployees---------idnamecompany_id
Here:
employees.company_id -> companies.id
Rails:
class Employee < ApplicationRecord belongs_to :companyendclass Company < ApplicationRecord has_many :employeesend
Now:
employee.company
finds one company:
SELECT *FROM companiesWHERE companies.id = employees.company_idLIMIT 1;
But:
company.employees
finds multiple employees:
SELECT *FROM employeesWHERE employees.company_id = 1;
Example data:
companiesid | name---+---------1 | Acme
employeesid | name | company_id---+------------+-----------10 | Alice | 111 | Bob | 112 | 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 :employeesend
Case B: One company can have only one employee
class Company has_one :employeeend
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 :companyend
You cannot automatically conclude:
class Company has_one :employeeend
It might be:
class Company has_many :employeesend
Think of it like this
Employee | | belongs_to vCompany
The question is:
How many employees can belong to the same company?
If:
1 employee -> 1 company1 company -> many employees
then:
Employee belongs_to CompanyCompany has_many Employees
If:
1 employee -> 1 company1 company -> 1 employee
then:
Employee belongs_to CompanyCompany has_one Employee
8. SQL makes this much clearer
Let’s compare the two.
has_one
users-----id
profiles--------iduser_id
Rails:
class User has_one :profileendclass Profile belongs_to :userend
SQL:
SELECT *FROM profilesWHERE profiles.user_id = 1LIMIT 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-----idtitleuser_id
Rails:
class User has_many :postsendclass Post belongs_to :userend
SQL:
SELECT *FROM postsWHERE posts.user_id = 1;
Now the database can have:
postsid | title | user_id---+----------------+---------1 | Hello Rails | 12 | ActiveRecord | 13 | PostgreSQL | 1
So:
user.posts
returns three records.
10. What about belongs_to on both sides?
You technically could write:
class A belongs_to :bendclass B belongs_to :aend
but then Rails expects:
a.b_idb.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 BB 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 :addressesendclass Address belongs_to :userend
Database:
addresses---------iduser_idstreetcity
If each user can have only one address:
class User has_one :addressendclass Address belongs_to :userend
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_oneandhas_many?”
Answer:
“First I locate the foreign key. The model containing the foreign key uses
belongs_to. On the parent side, I choosehas_oneorhas_manybased 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.