在rails中实现友谊模型的最佳方式

我想在我的应用程序中实现用户的朋友系统,所以我发现rails空间解决方案非常好,想法是在the Friendships table创建两行 :发送者邀请的第一行,接收者的第二行

用户之间的关系设置为has_many关联,如下所示:

 has_many :friendships has_many :friends, :through => :friendships, :conditions => "status = 'accepted'" 

接受用户为朋友的方法如下:

 # Accept a friend request. def self.accept(user, friend) transaction do accepted_at = Time.now accept_one_side(user, friend, accepted_at) accept_one_side(friend, user, accepted_at) end end 

accept_one_side()方法是:

 # Update the db with one side of an accepted friendship request. def self.accept_one_side(user, friend, accepted_at) request = find_by_user_id_and_friend_id(user, friend) request.status = 'accepted' request.accepted_at = accepted_at request.save! end 

这样做的好处是我们可以执行一个请求来获取双方的所有朋友(用户是发送邀请的人或朋友是谁发送的)

但我认为这有不利之处,例如在现实中有500个朋友,友谊表将包含“500X2 = 1000”行

第二个解决方案是与has_many through反向关联,如RailsCast#163 Self-Referential Association中所述 :

 has_many :friendships has_many :friends, :through => :friendships has_many :inverse_friendships, :class_name => "Friendship", :foreign_key => "friend_id" has_many :inverse_friends, :through => :inverse_friendships, :source => :user 

但是如果你想为一个用户获取所有朋友,你应该使用两个请求:

 user.friends user.inverse_friends 

如果你有一个巨大的友谊表,这不是最好的方式……

我想知道的是上面两个方法中最好的方法是什么,那么有一种优化方法吗? 如果还有另一种超级方法,我将感激不尽

我更喜欢在朋友之间需要两个连接的版本,每个方向一个。 原因与您提到的相同:它允许对用户的朋友进行更多类似Rails的查询。

此外,我认为为友谊请求(一个方向)和现有友谊(两个方向)设置不同的表格会更清楚

由于你在中间有一个友谊模型,我建议使用回调的魔力。 如果你定义了一些回调,那么你必须只需要为连接的一端带蛋糕,回调应该能够创建(或删除)匹配的补码。

 # in friendship_requests after_save :created_friendship def accept update_attributes(:status => 'accepted') end private def created_friendship sender.friends << receiver if status_changed? && status == 'accepted' end # in user.rb has_and_belongs_to_many :friends, after_add: :create_complement_friendship, after_remove: :remove_complement_friendship private def create_complement_friendship(friend) friend.friends << self unless friend.friends.include?(self) end def remove_complement_friendship(friend) friend.friends.delete(self) end 

这只是第一个想法,当然缺少一些validation器和回调......