79

I am trying to understand has_one relationship in RoR.

Let's say I have two models - Person and Cell:

class Person < ActiveRecord::Base
  has_one :cell
end

class Cell < ActiveRecord::Base
  belongs_to :person
end

Can I just use has_one :person instead of belongs_to :person in Cell model?

Isn't it the same?

Moon
  • 22,195
  • 68
  • 188
  • 269
  • The code above is incorrect, should be `has_one :cell` and `belongs_to :person` there should **not** be a space between the colon and the following word. – Josh Nov 23 '15 at 19:50

3 Answers3

187

No, they are not interchangable, and there are some real differences.

belongs_to means that the foreign key is in the table for this class. So belongs_to can ONLY go in the class that holds the foreign key.

has_one means that there is a foreign key in another table that references this class. So has_one can ONLY go in a class that is referenced by a column in another table.

So this is wrong:

class Person < ActiveRecord::Base
  has_one :cell # the cell table has a person_id
end

class Cell < ActiveRecord::Base
  has_one :person # the person table has a cell_id
end

And this is also wrong:

class Person < ActiveRecord::Base
  belongs_to :cell # the person table has a cell_id
end

class Cell < ActiveRecord::Base
  belongs_to :person # the cell table has a person_id
end

The correct way is (if Cell contains person_id field):

class Person < ActiveRecord::Base
  has_one :cell # the person table does not have 'joining' info
end

class Cell < ActiveRecord::Base
  belongs_to :person # the cell table has a person_id
end

For a two-way association, you need one of each, and they have to go in the right class. Even for a one-way association, it matters which one you use.

gorn
  • 5,042
  • 7
  • 31
  • 46
Sarah Mei
  • 18,154
  • 5
  • 45
  • 45
  • 1
    Nice answer. Seeing your answer I realize I read half the question. I'm sorry, but glad that you jumped in. + 10 – Pablo Fernandez May 14 '09 at 20:46
  • 6
    I've had to look this up a billion times. I wish they had thought through the naming a little better, to make it more clear which one goes where. – Sarah Mei May 15 '09 at 00:09
  • 20
    Great, now I know the two wrong answers. Would be better to show the "correct" way to show it. Just sayin'. – y0mbo Dec 09 '09 at 19:46
  • 110
    I always think of it in terms of Toy Story. Andy 'has_one' Woody, Woody 'belongs_to' andy. Where is the foreign key? On Woody's sole. – Michael Jan 31 '11 at 19:55
  • Thinking in terms of Toy Story really helps, so Woody has an 'andy_id' printed on his sole :) – patrick-fitzgerald Oct 31 '12 at 05:16
  • 12
    That's a cool mnemonic, but thought I'd share my mathematical method of remembering. has_one is like has_many, and has_many implies the key is on the other table since there is fixed number of columns defined on a SQL table. – gtd Dec 21 '12 at 05:49
  • @Mike that's so adorable. You're a delight. – Darth Egregious Apr 10 '15 at 14:22
15

If you add "belongs_to" then you got a bidirectional association. That means you can get a person from the cell and a cell from the person.

There's no real difference, both approaches (with and without "belongs_to") use the same database schema (a person_id field in the cells database table).

To summarize: Do not add "belongs_to" unless you need bidirectional associations between models.

Pablo Fernandez
  • 103,170
  • 56
  • 192
  • 232
  • 6
    The best line I have read today: "If you add "belongs_to" then you got a bidirectional association. That means you can get a person from the cell and a cell from the person." +1 – atw Aug 04 '16 at 10:06
7

Using both allows you to get info from both Person and Cell models.

@cell.person.whatever_info and @person.cell.whatever_info.
Jarrod
  • 2,398
  • 16
  • 14