How to Implement a Friendship Model in Rails 3 for a Social Networking Application? How to Implement a Friendship Model in Rails 3 for a Social Networking Application? ruby ruby

How to Implement a Friendship Model in Rails 3 for a Social Networking Application?


To access all pending friendships you can use an association:

has_many :pending_friends,         :through => :friendships,         :source => :friend,         :conditions => "confirmed = 0"  # assuming 0 means 'pending'

To make the friendship bidirectional, you may want to replace your boolean confirmed column with a string status column that has one of the following three values: 'pending', 'requested' and 'accepted' (optionally 'rejected'). This will help keep track of who made the friendship request.

When a friendship request is sent (say from Foo to Bar), you create two friendship records (encapsulated in a transaction): one requested and one pending to reflect resp. that Bar has a requested friendship from Foo and Foo has a pending friendship with Bar.

  def self.request(user, friend)    unless user == friend or Friendship.exists?(user, friend)      transaction do        create(:user => user, :friend => friend, :status => 'pending')        create(:user => friend, :friend => user, :status => 'requested')      end    end  end

When the friendship is accepted (e.g. by Bar), both friendship records are set to accepted.

  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  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 is largely covered in chapter 14 of the Railspace book by Michael Hartl and Aurelius Prochazka. Here's the source code which should help you refine your solution.


A short answer is yes. Just make another friendship record to represent bidirectional association.

I wrote a gem called has_friendship for this kind of problem. All you need to do is drop in has_friendship in your model, and all the associations and methods will be taken care of.

Hope this helps!