What's the difference between belongs_to and has_one?

Ruby on-RailsActiverecord

Ruby on-Rails Problem Overview


What is the difference between a belongs_to and a has_one?

Reading the Ruby on Rails guide hasn't helped me.

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

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.

Solution 2 - Ruby on-Rails

It's about where the foreign key sits.

class Foo < AR:Base
end
  • If foo belongs_to :bar, then the foos table has a bar_id column
  • If foo has_one :bar, then the bars table has a foo_id column

On 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)
)

Solution 3 - Ruby on-Rails

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.

Solution 4 - Ruby on-Rails

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

Solution 5 - Ruby on-Rails

has_one

  • This method should only be used if the other class contains the foreign key.

belongs_to

  • This method should only be used if the current class contains the foreign key.

Solution 6 - Ruby on-Rails

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
  • add a database unique index on the foreign key.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBlankmanView Question on Stackoverflow
Solution 1 - Ruby on-RailsryeguyView Answer on Stackoverflow
Solution 2 - Ruby on-RailsChandan Kumar MallikView Answer on Stackoverflow
Solution 3 - Ruby on-RailsillusionistView Answer on Stackoverflow
Solution 4 - Ruby on-RailsSomesh SharmaView Answer on Stackoverflow
Solution 5 - Ruby on-RailsKaiwen LuoView Answer on Stackoverflow
Solution 6 - Ruby on-RailskonyakView Answer on Stackoverflow