I know this question has been asked before on Stack Overflow, but the answers aren\'t doing it for me in ways I can explain. My general approach was inspired by this tutoria
This article shows how to set up reciprocal relationships: Bi-directional relationships in Rails
It shows how to use after_create
and after_destroy
to insert additional relationships that model the reciprocal relationship. In that way, you'd have double the records in your join table, but you'd have the flexibility of using a.friends
and b.friends
and seeing that both include each other correctly.
Making it work with your model:
class Person < ActiveRecord::Base
has_many :friendships, :dependent => :destroy
has_many :friends, :through => :friendships, :source => :person
end
class Friendship < ActiveRecord::Base
belongs_to :person, :foreign_key => :friend_id
after_create do |p|
if !Friendship.find(:first, :conditions => { :friend_id => p.person_id })
Friendship.create!(:person_id => p.friend_id, :friend_id => p.person_id)
end
end
after_update do |p|
reciprocal = Friendship.find(:first, :conditions => { :friend_id => p.person_id })
reciprocal.is_pending = self.is_pending unless reciprocal.nil?
end
after_destroy do |p|
reciprocal = Friendship.find(:first, :conditions => { :friend_id => p.person_id })
reciprocal.destroy unless reciprocal.nil?
end
end
I've used this approach successfully on a few projects, and the convenience is fantastic!