在OR上合并2个关系而不是AND

时间:2012-09-07 02:32:39

标签: ruby-on-rails ruby-on-rails-3 activerecord

我有两段代码,每条代码都在Micropost模型中返回一个关系。

scope :including_replies, lambda { |user| where("microposts.in_reply_to = ?", user.id)}

def self.from_users_followed_by(user)
  followed_user_ids = user.followed_user_ids
  where("user_id IN (?) OR user_id = ?", followed_user_ids, user)
end

当我运行r1 = Micropost.including_replies(user)时,我使用以下SQL得到两个结果的关系:

SELECT `microposts`.* FROM `microposts` WHERE (microposts.in_reply_to = 102) ORDER BY 
microposts.created_at DESC

当我运行r2 = Micropost.from_users_followed_by(user)时,我通过以下SQL获得与一个结果的关系:

SELECT `microposts`.* FROM `microposts` WHERE (user_id IN (NULL) OR user_id = 102) ORDER 
BY microposts.created_at DESC

现在当我合并像r3 = r1.merge(r2)这样的关系时,我的结果为零,但期待三次。原因是SQL看起来像这样:

SELECT `microposts`.* FROM `microposts` WHERE (microposts.in_reply_to = 102) AND 
(user_id IN (NULL) OR user_id = 102) ORDER BY microposts.created_at DESC

现在我需要的是(microposts.in_reply_to = 102) OR (user_id IN (NULL) OR user_id = 102) 我需要在合并关系中使用OR而不是AND

有办法做到这一点吗?

1 个答案:

答案 0 :(得分:1)

不直接使用Rails。 Rails没有公开任何方式将ActiveRelation(作用域)对象与OR合并。原因是ActiveRelation不仅可能包含条件(WHERE子句中描述的内容),还包含与OR合并的连接和其他SQL子句未明确定义的条件。

您可以直接使用Arel(ActiveRelation建立在其上),也可以使用Squeel,通过DSL公开Arel功能(可能更方便)。使用Squeel,ActiveRelations无法合并仍然很重要。但是,Squeel还提供Sifters,它表示可以使用的条件(没有任何其他SQL子句)。它会涉及将范围重写为sifters。