AREL中的分组和分组

时间:2011-11-10 16:56:21

标签: sql ruby arel

我正在尝试使用arel:

查询此sql代码段的等效内容
WHERE (("participants"."accepted" = 'f' AND "participants"."contact_id" = 1) 
  OR "participants"."id" IS NULL)

所以我想要(accepted && contact_id=1) OR NULL

这是我在AREL中得到的东西

participants[:accepted].eq(false).and(participants[:contact_id].eq(1).
  or(participants[:id].is(nil)

问题是,这会产生:

("participants"."accepted" = 'f' AND "participants"."contact_id" = 1 OR "participants"."id" IS NULL)

请注意我和条件周围缺少括号。我相信根据运营商的优先顺序,我得到了:

accepted && (contact_id=1 OR NULL)

在AREL查询中添加括号没有任何影响。有什么想法吗?

3 个答案:

答案 0 :(得分:25)

您可以使用Arel::Nodes::Grouping生成括号。

participants = Arel::Table.new("participants")

arel = participants.grouping(
  participants[:accepted].eq(false).and(participants[:contact_id].eq(1))
).or(participants[:id].eq(nil))

arel.to_sql # => (("participants"."accepted" = 'f' AND "participants"."contact_id" = 1) OR "participants"."id" IS NULL)

答案 1 :(得分:7)

  

我认为根据运算符优先级

问题在于AND has higher precedence than OR。因此1 AND 2 OR 3相当于(1 AND 2) OR 3。作为旁注:如果您使用像this one这样的包装器,您可以使用Arel编写更好看的代码:

User.where((User[:created_at] > 3.days.ago) & (User[:enabled] == true))

答案 2 :(得分:2)

为什么不翻转它们。应该相当于:

participants[:id].is(nil).or(participants[:accepted].eq(false).and(participants[:contact_id].eq(1))
希望我已经在上面设置了适当的parens,但是你明白我的意思了......