多对多的自我加入铁轨?

时间:2014-08-25 19:54:10

标签: ruby-on-rails activerecord

Rails文档提供了nice explanation如何处理自联接,其中只需要has_many-belongs_to关系。在该示例中,员工(作为经理)可以拥有许多员工(每个员工作为下属)。

但是,你如何处理has_many-has_many自联接(我之前听说过它被称为双向循环关联)?

例如,您如何处理员工以经理身份拥有多名下属的情况,以及以下属身份拥有多名经理?

或者,换句话说,用户可以关注多个用户并被许多用户关注?

1 个答案:

答案 0 :(得分:16)

用户可以包含多个:

  • 粉丝以跟随者身份
  • 以跟随者身份跟随。

以下是user.rb代码的外观:

class User < ActiveRecord::Base
  # follower_follows "names" the Follow join table for accessing through the follower association
  has_many :follower_follows, foreign_key: :followee_id, class_name: "Follow" 
  # source: :follower matches with the belong_to :follower identification in the Follow model 
  has_many :followers, through: :follower_follows, source: :follower

  # followee_follows "names" the Follow join table for accessing through the followee association
  has_many :followee_follows, foreign_key: :follower_id, class_name: "Follow"    
  # source: :followee matches with the belong_to :followee identification in the Follow model   
  has_many :followees, through: :followee_follows, source: :followee
end

以下是follow.rb的代码:

class Follow < ActiveRecord::Base
  belongs_to :follower, foreign_key: "follower_id", class_name: "User"
  belongs_to :followee, foreign_key: "followee_id", class_name: "User"
end

最值得注意的事项可能是user.rb中的:follower_follows:followee_follows。例如,要使用磨机(非循环)关联的运行,团队可能包含多个:players:contracts。这对于播放器也没有什么不同,播放器也可能有很多:teams:contracts(在此类播放器&#39;的职业生涯)。

但是在这种情况下,只存在一个命名模型(即用户),以相同方式命名through:relationship(例如through: :follow)会导致命名冲突,以便进行不同的使用连接表的情况(或访问点)。创建:follower_follows:followee_follows是为了避免这种命名冲突。

现在,用户可以有多个:followers:follower_follows和多个:followees:followee_follows

  • 要确定用户,请执行以下操作:跟随(在@user.followees调用数据库时),Rails现在可以查看class_name的每个实例:“Follow”,其中User是追随者(即foreign_key: :follower_id)通过:用户的:followee_follows。
  • 要确定用户:关注者(在@user.followers调用数据库时),Rails现在可以查看class_name的每个实例:“关注”这样的用户是关注者(即foreign_key: :followee_id)至:用户的:follower_follows。