什么时候应该在Rails中使用“has_many:through”关系?

我想了解什么has_many :through是什么时候使用它(以及如何)。 但是,我没有得到它。 我正在阅读Beginning Rails 3,我尝试了谷歌search,但我无法理解。

假设你有两个模型: UserGroup

如果你想让用户属于组,那么你可以做这样的事情:

 class Group < ActiveRecord::Base has_many :users end class User < ActiveRecord::Base belongs_to :group end 

如果你想跟踪关联的其他元数据呢? 例如,当用户join该组时,或者用户的angular色在该组中是什么?

这是您将关联设置为第一类对象的地方:

 class GroupMembership < ActiveRecord::Base belongs_to :user belongs_to :group # has attributes for date_joined and role end 

这将引入一个新表,并从用户表中删除group_id列。

这个代码的问题是,你必须更新每个你使用用户类的地方,并改变它:

 user.groups.first.name # becomes user.group_memberships.first.group.name 

这种types的代码很糟糕,而且会导致这样的改变。

has_many :through给你最好的两个世界:

 class User < ActiveRecord::Base has_many :groups, :through => :group_memberships # Edit :needs to be plural same as the has_many relationship has_many :group_memberships end 

现在你可以像正常的has_many一样对待它,但是当你需要的时候可以获得关联模型的好处。

请注意,你也可以用has_one来做到这一点。

编辑:可以轻松地将用户添加到组中

 def add_group(group, role = "member") self.group_associations.build(:group => group, :role => role) end 

假设你有这些模型:

 Car Engine Piston 

汽车has_one :engine
一个引擎belongs_to :car
引擎has_many :pistons
活塞belongs_to :engine

汽车has_many :pistons, through: :engine
活塞has_one :car, through: :engine

基本上,你正在委托一个模型的关系到另一个模型,所以不必打电话给car.engine.pistons ,你可以做car.pistons

ActiveRecord连接表

has_many :throughhas_and_belongs_to_many关系通过连接表起作用, 连接表是一个表示其他表之间关系的中间表。 与JOIN查询不同,数据实际上存储在一个表中。

实际差异

使用has_and_belongs_to_many ,您不需要主键,而是通过ActiveRecord关系访问logging,而不是通过ActiveRecord模型。 当您想要将两个模型链接成多对多的关系时,通常使用HABTM。

当您想要与连接表交互作为Rails模型时,您可以使用has_many :through关系,并使用主键和将自定义列添加到连接数据的function。 后者对于与连接行相关的数据尤为重要,但并不属于相关模型 – 例如,存储从连接行中的字段派生的计算值。

也可以看看

在“活动logging协会指南”中 ,build议如下:

最简单的经验法则是,如果您需要将关系模型作为一个独立的实体来使用,您应该build立一个has_many:through关系。 如果你不需要对关系模型做任何事情,build立一个has_and_belongs_to_many关系可能会更简单(尽pipe你需要记住在数据库中创build连接表)。

如果您需要validation,callback或join模型的额外属性,则应该使用has_many:through。

我会build议通过

http://guides.rubyonrails.org/association_basics.html

http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

这些是官方的轨道文件,并有很好的文件。

http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/has_many

这里还有ryan bates的截屏video:http: //railscasts.com/episodes/47-two-many-to-many

阅读 Rails教程和has_many的 这一部分:通过导轨部分 。

这篇文章应该解释你何时使用has_many :through