has_and_belongs_to_many vs has_many through

Moh*_*ain 75 ruby-on-rails

请通过关系解释has_and_belongs_to_many和has_many之间的区别.何时何地使用哪一个?

Dan*_*Dan 103

据我所知,has_and_belongs_to_many给你一个简单的查找表,引用你的两个模型.

例如,

故事可以属于许多类别.类别可以有很多故事.

Categories_Stories Table
story_id | category_id
Run Code Online (Sandbox Code Playgroud)

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

例如

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

因此,我们可以在中间使用订阅模型,这为我们提供了与前面示例类似的表,但具有其他属性.

Subscriptions Table
person_id | magazine_id | subscription_type | subscription_length | subscription_date 
Run Code Online (Sandbox Code Playgroud)

等等.

  • 请注意,表格需要按字母顺序命名,即categories_stories表格而不是stories_categories - 这是使其有效的惯例. (34认同)
  • 这里的要点是,您迟早“总是”最终需要向连接表添加属性。继续从一开始就使用“has_many through:”,这样可以避免以后的痛苦。如果事实证明你不添加属性......你仍然没有失去任何东西。 (2认同)

Tad*_*kas 37

来自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.

  • 我还要补充一点,有许多方法将rails插入has_and_belongs_to_many而不是has_many:through.所有的方法,比如为关联分配一组值,似乎都没有在has_many的文档中显示:通过http://guides.rubyonrails.org/association_basics.html#has_and_belongs_to_many-association-reference (3认同)

dav*_*ber 14

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


yoz*_*zzz 7

根据我的经验,使用它总是更好,has_many: through因为您可以向表添加时间戳。很多时候,在调试一些ActiveRecord通过 HABTM 连接的对象时,我缺少created_at时间戳updated_at来获取实际发生情况的线索。

因此请记住,它可以帮助您调试、调查当时上下文中的数据关系问题,因为没有它,您在创建或更新关系时就会“盲目”。


And*_*ado 5

如果您需要在连接模型上进行验证、回调或额外属性,则应该使用 has_many :through 。


小智 5

许多答案都阐明,如果您不需要在连接表上进行任何额外的数据或验证,则应该使用has_and_belongs_to_manyvs .。has_many through:

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

  • 您能解释一下为什么这会很危险并且容易出现错误吗?HABTM 与 has_many :through _相同_,只是没有模型。您可以非常优雅地将 HABTM 转换为虽然。 (2认同)