Rails: belongs_to vs has_one
Asked Answered
L

4

35

A bit of a newbie question on rails associations.

I have a Bug model, and a Status model. Status is basically just a key/value pair table. Out of the choices available, I would say Bug has_one Status makes the most sense. However, according to this

Content belongs_to ContentTemplate. Go back and look at how I described the problem, and you'll see that it works. With belongs_to, the table accepts responsibility for the foreign key. So Content has a content_template_id. And ContentTemplate doesn't need anything. I can point to it at will. Done.

Bug belongs_to Status would be more appropriate (since Bug should take the foreign key). Semantically, his example makes sense, but mine makes none. Is this just a quirk of rails where in this situation it looks odd, or am I not understanding something/doing it wrong?

Loge answered 22/5, 2009 at 21:0 Comment(0)
E
20

Yes, I think you've just found a slightly odd-looking scenario in Rails. I suppose it might be useful to view "status" as a sort of category to which the bug belongs — in that light, it makes sense.

Edema answered 22/5, 2009 at 21:45 Comment(1)
I guess it stands as a testament to how nicely rails works semantically, that hitting this situation I was like "I must be doing it wrong"Loge
S
9
TABLE:
    Bug
    id integer
    desc string
    status_id integer fk

    Status
    id integer
    desc string

RAILS MODEL:
    Bug
    belongs_to :status

    Status
    has_many :bugs
Selective answered 22/5, 2009 at 21:30 Comment(4)
Bug would take the foreign key because a status can have many bugs, but a bug has only one status at a time.Edema
Your new solution is how we think of the situation, but it will not work. When you do bug.status, it will look for a bug_id column in status, which does not exist. A has_one or has_many needs to be matched by a belongs_to in the class that is being "had".Edema
How would you change it? Feel free to copy my answer into yours and make changes there if you prefer. I'm just curious to know what you think the models should look like.Selective
It should be Bug.belongs_to :status, like the asker guessed. It looks awkward, but that's the way Rails needs the relationship to be expressed AFAIK. The belongs_to means "my table has the foreign key." That way bug.status and status.bugs will both work correctly.Edema
I
1

You didn't explain precisely what kind of relationship between Bug and Status you would like to get, but I assume you are interested in one of the following:

  • one-to-many: in this case there should be has_many in Bug class and belongs_to in Status class,
  • one-to-one: in this case there should be has_one in Bug class and belongs_to in Status class.

In both cases Status contains the foreign key. In the second case the wording is a little odd, due to the fact that one-to-one relationship is in fact asymmetric (there should be a FK on one side only).

Inefficiency answered 22/5, 2009 at 21:52 Comment(2)
The problem is that a bug does not have many statuses at a time, either conceptually or in a proper implementation. Conceptually, we think of a status as belonging to many bugs, but Rails can only express this as a status having many bugs.Edema
@chuck: That is pretty much it. One-to-Many vs Many-to-One. Logically, pretty much equivalent, but conceptually there is a differenceLoge
S
0

If Status is just a look-up/key-value table, it sounds like you might want a habtm(has_and_belongs_to_many) relationship between Status and Bug. With habtm, what you'll end up with is a bugs_statuses join table that has bug_id and status_id columns along with your bugs and statuses tables.

Shiflett answered 22/5, 2009 at 21:24 Comment(2)
That is for many-to-many relationships, which this is not. This is a many-to-one. My question is basically around that the wording for that relationship only makes sense in a one-to-many, not a many-to-one, and if there is a more elegant way to handle it.Loge
Understood. I guess my typical thinking of "Bugs" and their "Status" is that a Bug could be in multiple statuses at once (ex. "worksforme" and "open") or you may want to keep the history of a Bug's status.Shiflett

© 2022 - 2024 — McMap. All rights reserved.