title: the best way to implement a friendship model in rails
body: <p>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 <strong>two lines</strong> in <code>the Friendships table</code> : the first line for the sender invitation, and the second one for receiver</p>
  <p>relation between users is setup with <code>has_many</code> association like this:</p>
  <pre><code>has_many :friendships
  has_many :friends, :through =&gt; :friendships, :conditions =&gt; &quot;status = 'accepted'&quot;
  </code></pre>
  <p>method for accepting a user as friend is like this :</p>
  <pre><code># 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 
  </code></pre>
  <p>accept_one_side() method is :</p>
  <pre><code># 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
  </code></pre>
  <p>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)</p>
  <p>but i think this have disadvantage if for example in reality there is 500 friends, Friendships table will contains &quot;500X2 = 1000&quot; lines</p>
  <p>the second solution is to make a reverse association with <code>has_many through</code> like explained in <a href="http://railscasts.com/episodes/163-self-referential-association" rel="nofollow noreferrer">RailsCast #163 Self-Referential Association</a> :</p>
  <pre><code>has_many :friendships
  has_many :friends, :through =&gt; :friendships
  has_many :inverse_friendships, :class_name =&gt; &quot;Friendship&quot;, :foreign_key =&gt; &quot;friend_id&quot;
  has_many :inverse_friends, :through =&gt; :inverse_friendships, :source =&gt; :user
  </code></pre>
  <p>but here if you want to get all friends for a user you should use two request for that :</p>
  <pre><code>user.friends
  user.inverse_friends
  </code></pre>
  <p>which is not the best way at all if you have a huge Friendships table ...</p>
  <p>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</p>