module FriendshipPlugin module UserExtensions def self.included( recipient ) recipient.extend( ClassMethods ) end module ClassMethods def has_friendships has_many :friendships, :foreign_key => 'user_id', :class_name => 'Friendship' has_many :befriendships, :foreign_key => 'friend_id', :class_name => 'Friendship' has_many :friends, :through => :friendships, :source => :befriendshipped, :conditions => "accepted_at IS NOT NULL" has_many :befrienders, :through => :befriendships, :source => :friendshipped attr_protected :friend_ids attr_protected :befriender_ids include FriendshipPlugin::UserExtensions::InstanceMethods end end module InstanceMethods # Finds friendship, pending or accepted, between self and another user object def friendships_with( user_obj ) Friendship.find(:all, :conditions => ['(user_id=? and friend_id=?) OR (user_id=? and friend_id=?)', self.id, user_obj.id, user_obj.id, self.id ] ) end # Provides a quick way to see if a user is a friend of another def is_friends_with?( user_obj ) self.friends.include?( user_obj ) end # Add a user as requesting a friendship def request_friendship_of( user_obj ) Friendship.create!(:friendshipped => self, :befriendshipped => user_obj) end # All pending friendship requests def pending_friendships Friendship.find(:all, :conditions => ["friend_id = ? AND accepted_at IS NULL", id]) end # Accept a specific pending friendship, creating a 2 way friendship def accept_friendship( friendship_obj ) friendship_obj.update_attribute(:accepted_at, Time.now) Friendship.create!( :befriendshipped => friendship_obj.friendshipped, :friendshipped => self, :accepted_at => Time.now) end def accept_friendship_of ( user_obj ) self.friendships_with( user_obj ).each { |friendship| self.accept_friendship(friendship) } end # Deny/Delete a specific pending friendship def deny_friendship( friendship_obj ) friendship_obj.destroy end # Directly creates a 2 way friendship without intervention def is_friends_with( user_obj ) unless self.is_friends_with? user_obj Friendship.create( :befriendshipped => self, :friendshipped => user_obj, :accepted_at => Time.now ) Friendship.create( :befriendshipped => user_obj, :friendshipped => self, :accepted_at => Time.now ) else self.friendships_with(user_obj).first end end # Directly remove both sides of any friendship without intervention def is_not_friends_with( user_obj ) self.friendships_with(user_obj).each do |friendship| friendship.destroy end end end end end