c = "(f.profile_id = #{self.id} OR f.friend_id = #{self.id})"
c += AND + "(CASE WHEN f.profile_id=#{self.id} THEN f.friend_id ELSE f.profile_id END = p.id)"
c += AND + "(CASE WHEN f.profile_id=#{self.id} THEN f.profile_rejected ELSE f.friend_rejected END = 1)"
c += AND + "(p.banned = 0)"
我想这能在这样的关系的has_many使用:
has_many :removed_friends, :conditions => ???
如何设置在那里的self.id?或者我如何通过那里的ID? 然后我想用will_paginate插件:
@profile.removed_friends.paginate(:page => 1, :per_page => 20)
谢谢你的帮助
编辑:
class Profile < ActiveRecord::Base
has_many :friendships
has_many :removed_friends, :class_name => 'Profile', :through => :friendships, :conditions =>
"(friendships.profile_id = #{self.id} OR friendships.friend_id = #{self.id})"
"AND (CASE WHEN friendships.profile_id=#{self.id} THEN friendships.profile_rejected ELSE friendships.friend_rejected END = 1)" +
"AND (p.banned = 0)"
end
class Friendship < ActiveRecord::Base
belongs_to :profile
belongs_to :removed_friend, :class_name => 'Profile', :foreign_key => "(CASE WHEN friendships.profile_id = #{self.id} THEN friend_id ELSE profile_id END)"
end
使用单引号括住的条件:
class Profile < ActiveRecord::Base
has_many :friendships
has_many :removed_friends, :class_name => 'Profile', :through => :friendships,
:conditions => '
( friendships.profile_id = #{self.id} OR
friendships.friend_id = #{self.id}
) AND
(CASE WHEN friendships.profile_id=#{self.id}
THEN friendships.profile_rejected
ELSE friendships.friend_rejected
END = 1
) AND
(p.banned = 0)'
end
You might want to break this down into a series of named scopes that can be applied in stages instead of all at once. As an example, extract the banned part:
class Friend < ActiveRecord::Base
named_scope :banned, lambda { |*banned| {
:conditions => { :banned => banned.empty? ? 1 : (banned.first ? 1 : 0) }
}}
end
@profile.friends.removed.banned(false).paginate(:page => 1, :per_page => 20)
Using heavy-duty conditions in relationships is bound to cause trouble. If possible, try denormalizing the table, creating derivative columns that have "easy" versions of the data, or other things to make querying it easier.
你真的有在这里两个关系。 你有:
- 从被拒绝的友谊
profile_id
侧 - 从被拒绝的友谊
friend_id
侧
我不知道为什么双方都可以拒绝的友谊,也许你需要看看你的模型一点点在这里(哪一方请求呢?会不会更好考虑请求者取消了请求,而不是说它的从被拒绝profile
的一面呢?)
无论如何,我想这个模型作为两个独立的关系,他们是:
class Profile
has_many :rejected_friendships, :conditions => 'friendships.profile_rejected = 1'
has_many :canceled_friendships, :foreign_key => 'friend_id', :conditions => 'friendships.friend_rejected = 1'
named_scope :banned, lambda do |*banned|
{ :conditions => {:banned => banned.empty? ? 1 : (banned.first ? 1 : 0) } }
end
has_many :rejected_friends, :class_name => 'Profile', :through => :rejected_friendships
has_many :canceled_friends, :class_name => 'Profile', :through => :canceled_friendships
def removed_friends
(self.rejected_friends.banned(false).all + self.canceled_friends.banned(false).all).uniq
end
end
这有点不可取的,因为removed_friends是不是有关系了,所以你不能做这样的事情Profile.removed_friends.find(:all, :conditions => {:name => "bleh"})
了,但是这是一个相当复杂的案件。 这个条件是相当复杂的。