在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器和回调......