What is the difference between a belongs_to
and a has_one
?
Reading the Ruby on Rails guide hasn't helped me.
What is the difference between a belongs_to
and a has_one
?
Reading the Ruby on Rails guide hasn't helped me.
They essentially do the same thing, the only difference is what side of the relationship you are on. If a User
has a Profile
, then in the User
class you'd have has_one :profile
and in the Profile
class you'd have belongs_to :user
. To determine who "has" the other object, look at where the foreign key is. We can say that a User
"has" a Profile
because the profiles
table has a user_id
column. If there was a column called profile_id
on the users
table, however, we would say that a Profile
has a User
, and the belongs_to/has_one locations would be swapped.
here is a more detailed explanation.
It's about where the foreign key sits.
class Foo < AR:Base
end
belongs_to :bar
, then the foos table has a bar_id
columnhas_one :bar
, then the bars table has a foo_id
columnOn the conceptual level, if your class A
has a has_one
relationship with class B
then class A
is the parent of class B
hence your class B
will have a belongs_to
relationship with class A
since it is the child of class A
.
Both express a 1-1 relationship. The difference is mostly where to place the foreign key, which goes on the table for the class declaring the belongs_to
relationship.
class User < ActiveRecord::Base
# I reference an account.
belongs_to :account
end
class Account < ActiveRecord::Base
# One user references me.
has_one :user
end
The tables for these classes could look something like:
CREATE TABLE users (
id int(11) NOT NULL auto_increment,
account_id int(11) default NULL,
name varchar default NULL,
PRIMARY KEY (id)
)
CREATE TABLE accounts (
id int(11) NOT NULL auto_increment,
name varchar default NULL,
PRIMARY KEY (id)
)
has_one
and belongs_to
generally are same in a sense that they point to the other related model. belongs_to
make sure that this model has the foreign_key
defined.
has_one
makes sure that the other model has_foreign
key defined.
To be more specific, there are two sides of relationship
, one is the Owner
and other is Belongings
. If only has_one
is defined we can get its Belongings
but cannot get the Owner
from the belongings
. To trace the Owner
we need to define the belongs_to
as well in the belonging model.
One additional thing that I want to add is, suppose we have the following models association.
class Author < ApplicationRecord
has_many :books
end
If we only write the above association, then we can get all books of a particular author with
@books = @author.books
but, for a particular book, we can't get the corresponding author with
@author = @book.author
To make the above code work we need to add an association to the Book
model as well, like this
class Book < ApplicationRecord
belongs_to :author
end
This will add method 'author' to the Book
model. For mode details see guides
has_one
other class
contains the foreign key
.belongs_to
current class
contains the foreign key
.As many (all?) other answers have pointed out, it's all about where the foreign key is stored.
But that's not necessarily very memorable, so this way of thinking about it may help you:
Therefore the foreign key (a reference to the owner) always goes on the thing (record) that is owned, not a record of the possession on the owner.
From a simplicity standpoint, belongs_to
is better than has_one
because in has_one
, you would have to add the following constraints to the model and table that has the foreign key to enforce the has_one
relationship:
validates :foreign_key, presence: true, uniqueness: true
Here's the most reliable memory tool I use to remember the direction of has_many/one and belongs_to:
You write your name on the stuff that belongs to you. Your notebook or driver's license has your name written on it. You might have many notebooks and one driver's license...but all of them belong to only one person.
A child record that belongs to a parent/owning record always has the name of the owning record written on it. That is, child.owner_id
is written on the child record, which belongs to the parent record.
The parent record has nothing written on it to identify the child records that has_many of. Just like you don't tattoo book titles or license numbers on your body.