导轨的has_many条件(Rails has_many conditions)

2019-10-20 18:45发布

    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

Answer 1:

使用单引号括住的条件:

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


Answer 2:

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.



Answer 3:

你真的有在这里两个关系。 你有:

  • 从被拒绝的友谊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"})了,但是这是一个相当复杂的案件。 这个条件是相当复杂的。



文章来源: Rails has_many conditions