Rails: belongs_to vs has_one

35
一道有关Rails关联的新手问题。
我有一个Bug模型和一个Status模型。Status基本上只是一个键/值对表。在可用的选择中,我会说Bug has_one Status是最合适的。然而,根据这个
“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更为合适(因为Bug应该接受外键)。从语义上讲,他的例子很有道理,但我的没有。这只是Rails的一个怪癖,在这种情况下看起来很奇怪,还是我没有理解什么/做错了?
4个回答

20

是的,我认为你刚刚在 Rails 中发现了一个稍微看起来有些奇怪的场景。我想把 "status" 视作一个类别,表示该 bug 属于哪种类别——从这个角度来看,这样做就很有意义。


4
我猜这证明了Rails的语义非常好,当我碰到这种情况时,我会想,“我一定是做错了什么”。 - Matt Briggs

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

2
Bug会获取外键,因为一个状态可以有多个Bug,但是一个Bug在同一时间只有一个状态。 - Chuck
你的新解决方案是我们考虑到这种情况的方式,但它不会起作用。当你执行bug.status时,它将在status中查找一个名为bug_id的列,但该列不存在。一个has_one或has_many需要与被“拥有”的类中的belongs_to匹配。 - Chuck
你会如何改变它?如果你愿意,可以将我的答案复制到你的答案中并进行修改。我只是好奇你认为模型应该是什么样子的。 - Willem Obst
1
应该是Bug.belongs_to :status,就像提问者猜测的那样。这看起来很尴尬,但据我所知,这是Rails需要表达关系的方式。 belongs_to 意味着“我的表有外键”。这样 bug.status 和 status.bugs 这两个属性都能正常工作。 - Chuck

1
你没有明确解释Bug和Status之间想获得什么样的关系,但我假设你对以下一种感兴趣:
  • 一对多:在这种情况下,Bug类应该有has_many,而Status类应该有belongs_to
  • 一对一:在这种情况下,Bug类应该有has_one,而Status类应该有belongs_to

在两种情况下,Status都包含外键。在第二种情况下,措辞有点奇怪,因为一对一的关系实际上是不对称的(只有一侧应该有一个FK)。


1
问题在于一个 bug 同时不能有多个状态,无论是从概念上还是在实际实现中都是如此。从概念上来说,我们认为一个状态 属于 许多 bug,但 Rails 只能将其表达为一个状态拥有许多 bug。 - Chuck
@chuck:就是这样了。一对多 vs 多对一。从逻辑上说,它们基本等价,但在概念上有所不同。 - Matt Briggs

0
如果Status只是一个查找/键值表,那么您可能希望在Status和Bug之间建立 habtmhas_and_belongs_to_many)关系。使用habtm,最终你将会得到一个 bugs_statuses 连接表,其中包括了 bug_id status_id 列以及您的bugs和statuses表。

这是针对多对多关系的,但这并不是。这是一个多对一关系。我的问题基本上围绕着那种关系的措辞只在一对多关系中有意义,而不是在多对一关系中,是否有更优雅的处理方法。 - Matt Briggs
明白了。我想我的典型思维是“漏洞”及其“状态”,一个漏洞可以同时处于多个状态(例如,“worksforme”和“open”),或者您可能希望保留漏洞状态的历史记录。 - rnicholson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接