If you use Arel expressions for the where relation, you can untie these methods and reconnect them to the friends association:
class User < ActiveRecord::Base has_many :friendships do def accepted where(Friendship.arel_table[:status].eq('accepted')) end def rejected where(Friendship.arel_table[:status].eq('rejected')) end end has_many :friends, through: :friendships do def accepted proxy_association.owner.friendships.extensions.first.instance_method(:accepted).bind(self).call end def rejected proxy_association.owner.friendships.extensions.first.instance_method(:rejected).bind(self).call end end end
SQL will be generated correctly with this code, so this test will pass:
def test_stuff tom = User.create! name: "tom" fred = Friend.create! name: "fred" jerry = Friend.create! name: "jerry" Friendship.create! user: tom, friend: fred, status: 'accepted' Friendship.create! user: tom, friend: jerry, status: 'rejected' tom.reload fred.reload assert_equal "fred", tom.friends.accepted.first.name assert_equal "jerry", tom.friends.rejected.first.name end
source share