views:

614

answers:

5

This is a continuation of this question: Original Question (SO)

The answer to this question involved the following set of models:

class User < ActiveRecord::Base
  has_many :friendships
  has_many :friends, :through => :friendships #...
end

class Friendship < ActiveRecord::Base
  belongs_to :user
  belongs_to :friend, :class_name => 'User', :foreign_key => 'friend_id'
end 

<% for friendship in @user.friendships %>
  <%= friendship.status %>
  <%= friendship.friend.firstname %>
<% end %>

This works fine if say, I have a user and I want to get all the "friendships" for which his or her id is the :user_id FK on the Friendship model. BUT, when I run something like

@user.friendships.friends

I would like it to return all User records for which that User is either the :user or the :friend in the friendship - so, in other words, return all friendships in which that user is involved.

Hopefully the above makes sense. I'm still quite new to rails and hope there is a way to do this elegantly without making just a standard link table or providing custom SQL.

Thank you!

Tom

+2  A: 

You cannot just use @user.friendships here because it will only give you those friendships where @friendship.user_id == @user.id. The only thing I can think of right now is just to do

Friendship.find_by_user_id(@user.id).concat Friendship.find_by_friend_id(@user.id)
neutrino
+1  A: 

There is a similiar question with a good answer found here: link table with foreign keys

Tilendor
+2  A: 

railscasts episode on this topic

lego
This looks promising. Thanks.
cakeforcerberus
A: 

From the railscast link:

# models/user.rb
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
cakeforcerberus
A: 

my solution is a a scope:

# model
class Message < ActiveRecord::Base
  belongs_to :sender, :class_name => "User"
  belongs_to :recipient, :class_name => "User"

  scope :of_user, lambda { |user_id| where("sender_id = ? or recipient_id = ?",
        user_id,  user_id) }
end


# in controller
@messages = Message.of_user(current_user)
airy