我是否需要为HABTM连接表手动创建迁移?


77

我正在努力使HATBM正常工作。我有一个很烂的scanario:文章和标签。我认为,这里应该使用HABTM,因为它是多对多的关系。但是我不知道是否应该手动创建联接表(在这种情况下为articles_tags)。

我的代码目前如下:

class Article < ActiveRecord::Base
  has_and_belongs_to_many :tags  
end

class Tag < ActiveRecord::Base
  has_and_belongs_to_many :articles
end

当我运行迁移时,没有创建第三个表。另外,我想补充一点,我的第三个表不包含任何域逻辑,只是盲目的分配。

我正在使用Rails 2.2.2


1
即使在第4轨上,我也想答案是...。:(
dtc

1
@dtc,仍然是,仍然正确。
Valentin Vasilyev

Answers:


141

您应该在迁移其中一个表时执行此操作,或者如果已运行这些迁移,则应在单独的迁移中执行此操作:

create_table :articles_tags, :id => false do |t|
  t.references :article, :tag
end

add_index :articles_tags, [:article_id, :tag_id]

这将为您和 :id => false告诉Rails不要向该表添加id字段。还有一个索引,它将加速此联接表的查找。

您还可以为此生成一个模型(ArticlesTag)并执行以下操作:

# article.rb
has_many :articles_tags
has_many :tags, :through => :articles_tags

# tag.rb
has_many :articles_tags
has_many :articles, :through => :articles_tags

# article_tag.rb
belongs_to :tag
belongs_to :article

然后在从script/generate model articles_tag调用生成的迁移中创建表。


谢谢,雷达,这就是我所需要的!
瓦伦丁·瓦西里耶夫

12
有趣的是,官方指南或文档没有说明这一点。我不得不深入研究Stackoverflow。泰
lzap 2011年

如果您想使用联接的唯一名称来关联它们,因为该联接已被使用,该怎么办。
旅行

我认为您应该通过add_index :articles_tags, [:article_id, :tag_id]change方法结束之前添加来添加索引以加入表
Giovanni Cappellotto 2012年

@乔凡尼:完成。谢谢!
Ryan Bigg


7

您可能还想向迁移添加索引:

add_index“ articles_tags”,“ article_id”

add_index“ articles_tags”,“ tag_id”

但是,如果您想标记功能,我建议使用acts_as_taggable_on rails插件:

http://www.intridea.com/tag/acts_as_taggable_on http://github.com/mbleigh/acts-as-taggable-on/

我已经在项目中使用了它,并且非常容易实现。

用于标记的联接表的问题之一是,它很容易为您希望使其可标记的每种内容类型创建联接表(例如,comment_tags,posts_tags,images_tags等)。该插件使用包含区分符的标签表来确定内容类型,而无需为每种类型使用特定的联接表。


迁移方法引用(或belongs_to)会自动添加索引。您不需要那个。您可以使用它来中断迁移。
lzap 2011年

迁移方法引用(或belongs_to)实际上不会自动添加索引。(他们认为:-)
lzap 2011年

恕我直言,最好创建一个复合主键。但这是特定于数据库的。
Art Shayderov 2011年

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.