Has_many通过协会扩展

时间:2011-06-24 15:27:00

标签: ruby-on-rails ruby

是否可以通过关联扩展设置多个?我有:

class User < ActiveRecord::Base

  has_many :friendships do
    def accepted
      where status: "accepted"
    end
    def rejected
      where status: "rejected"
    end
  end

  has_many :friends, through: :friendships do
    def accepted
      # Something equivalent to the following using association extension:
      # where("friendships.status = 'accepted'")
    end
    def rejected
      # Something equivalent to the following using association extension:
      # where("friendships.status = 'rejected'")
    end
  end

end

如何使用友谊关联扩展程序设置我的朋友关联(通过友谊)?

2 个答案:

答案 0 :(得分:0)

我想到的第一件事是:

class User < ActiveRecord::Base

  has_many :accepted_friendships, :class_name => "Friendship", :conditions => ...
  has_many :accepted_friends, through => :accepted_friendhips, :source => :friend

end

答案 1 :(得分:0)

如果对where关系使用Arel表达式,则可以取消绑定这些方法并将它们重新绑定到friends关联:

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将正确生成,因此该测试通过:

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