has_and_belongs_to_many vs has_many通过


Answers:


107

据我所记得,has_and_belongs_to_many它为您提供了一个简单的查询表,该表引用了您的两个模型。

例如,

故事可以分为许多类别。类别可以有很多故事。

Categories_Stories Table
story_id | category_id

has_many :through 为您提供了第三个模型,该模型可用于存储不属于任何原始模型的其他各种信息。

例如

人可以订阅许多杂志。杂志可以有很多订阅者。

因此,我们可以在中间有一个订阅模型,该模型为我们提供了与先前示例类似的表,但具有其他属性。

Subscriptions Table
person_id | magazine_id | subscription_type | subscription_length | subscription_date 

等等。


37
请注意,该表需要按字母顺序命名,即Categories_stories表,而不是stories_categories-这是使它起作用的约定。
威尔

谢谢,我现在更改了帖子

为什么必须按字母顺序@Will?
ctilley79 2012年

@ ctilley79是使用的约定。因此,在建立协会后,它知道要查找的表
Will

@会好吧。我会试试看。
ctilley79 2012年

38

来自http://guides.rubyonrails.org/association_basics.html#choosing-between-has-many-through-and-has-and-belongs-to-many

最简单的经验法则是,如果需要将关系模型作为独立实体使用,则应设置has_many:through关系。如果您不需要对关系模型做任何事情,则设置has_and_belongs_to_many关系可能更简单(尽管您需要记住要在数据库中创建联接表)。如果需要在连接模型上进行验证,回调或其他属性,则应使用has_many:through。


3
我还要补充一点,有很多方法可以将rails插入has_and_belongs_to_many而不是has_many:through。为has_many的文档中似乎未显示所有方法(如为关联分配值的集合):通过guides.rubyonrails.org/…– e3matheus 2012
01

15

我的经验法则是,我可以在此处获得复选框列表吗?如果是这样,那就是一个habtm协会。如果我需要复选框以捕获有关该关系的更多信息,而不仅仅是它是/不是,那么请使用has_many:through。HABTM就像将_ids方法与simple_form collection_check_boxes一起使用一样简单。Has_many:through通常涉及accepts_nested_attributes_for。



2

许多答案表明,如果不需要在连接表上添加任何额外数据或验证,则应使用has_and_belongs_to_manyvs。has_many through:

但是,请注意采用这种方法。在应用程序开发的早期阶段,几乎不可能知道在项目生命周期的不久将来可能需要哪些额外的功能或验证。如果您决定使用has_and_belongs_to_many,并希望在未来两年内添加一个简单的数据点或验证,则迁移此更改将非常困难且容易出错。为了安全起见,默认为has_many :through


1
您能解释为什么这很危险并且容易出错吗?HABTMhas_many:through相同,只是没有模型。您可以非常优雅地将HABTM转换为if。
grepsedawk

1
这里有一个很好的回答你的问题,@grepsedawk:flatironschool.com/blog/...
大卫Hempy

2

根据我的经验,最好总是使用它,has_many: through因为您可以在表中添加时间戳。很多时候,在调试一些ActiveRecord是通过HABTM连接的对象,我失踪了created_atupdated_at时间戳得到什么实际发生的线索。因此请记住,它可以帮助您在时间范围内调试,调查与数据关系有关的问题,因为如果没有它,则在创建或更新关系时您将是“盲目的”。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.