I want to implement a user's friends system in my app so i found the rails space solution very nice, the idea there is to create two lines in the Friendships table
: the first line for the sender invitation, and the second one for receiver
relation between users is setup with has_many
association like this:
has_many :friendships
has_many :friends, :through => :friendships, :conditions => "status = 'accepted'"
method for accepting a user as friend is like this :
# 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() method is :
# 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
this have advantage that we can executing one request to get all friends from the two side (either the user is who sent the invitation or the friend is who sent it)
but i think this have disadvantage if for example in reality there is 500 friends, Friendships table will contains "500X2 = 1000" lines
the second solution is to make a reverse association with has_many through
like explained in 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
but here if you want to get all friends for a user you should use two request for that :
user.friends
user.inverse_friends
which is not the best way at all if you have a huge Friendships table ...
what i want to know is what is the best one method from the two above, then there is a way to optimize it ? if there is also another super method i will be thankful