在轨道中使用相同型号的多对多关系?

时间:2010-01-30 15:55:23

标签: ruby-on-rails

如何在rails中与同一模型建立多对多关系?

例如,每个帖子都连接到很多帖子。

6 个答案:

答案 0 :(得分:264)

答案 1 :(得分:15)

回答施蒂夫提出的问题:

双向循环协会

用户之间的跟随者 - 关注者关系是双向循环关联的一个很好的例子。 用户可以包含多个:

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

以下是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(在播放器的职业生涯中) 。但在这种情况下,只存在一个命名模型(即用户),相同地命名through:relationship(例如through: :follow,或者,就像上面的帖子示例中所做的那样,{ {1}})会导致连接表的不同用例(或访问点)的命名冲突。创建through: :post_connections:follower_follows是为了避免这种命名冲突。现在,用户可以有多个:followee_follows:followers和多个:follower_follows:followees

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

答案 2 :(得分:6)

如果有人来到这里试图找出如何在Rails中创建朋友关系,那么我会将它们引用到我最终决定使用的内容,即复制“社区引擎”所做的事情。

您可以参考:

https://github.com/bborn/communityengine/blob/master/app/models/friendship.rb

https://github.com/bborn/communityengine/blob/master/app/models/user.rb

了解更多信息。

TL; DR

# user.rb
has_many :friendships, :foreign_key => "user_id", :dependent => :destroy
has_many :occurances_as_friend, :class_name => "Friendship", :foreign_key => "friend_id", :dependent => :destroy

...

# friendship.rb
belongs_to :user
belongs_to :friend, :class_name => "User", :foreign_key => "friend_id"

答案 3 :(得分:1)

对于双向belongs_to_and_has_many,请参阅已发布的优秀答案,然后使用其他名称创建另一个关联,反转外键并确保将class_name设置为指向正确的模型。欢呼声。

答案 4 :(得分:1)

受@StéphanKochen的启发, 这可能适用于双向关联

class Post < ActiveRecord::Base
  has_and_belongs_to_many(:posts,
    :join_table => "post_connections",
    :foreign_key => "post_a_id",
    :association_foreign_key => "post_b_id")

  has_and_belongs_to_many(:reversed_posts,
    :class_name => Post,
    :join_table => "post_connections",
    :foreign_key => "post_b_id",
    :association_foreign_key => "post_a_id")
 end

然后post.posts&amp;&amp; post.reversed_posts应该都有效,至少对我有用。

答案 5 :(得分:0)

如果有人在获得优秀工作答案方面遇到问题,例如:

  

(对象不支持#inspect)
  =&GT;

  

NoMethodError:未定义方法`split'for:Mission:Symbol

然后解决方案是用:PostConnection替换"PostConnection",当然替换你的类名。