ruby AREL中的“与”和“或”

lc8prwob  于 2023-10-17  发布在  Ruby
关注(0)|答案(4)|浏览(113)

我尝试使用arel查询这个sql代码片段的等价物:

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

所以我想要(accepted && contact_id=1) OR NULL
这是我在阿瑞尔找到的

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)

注意my和conditions周围缺少括号。我 * 相信 * 根据运算符优先级,我得到:

accepted && (contact_id=1 OR NULL)

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

vxbzzdmp

vxbzzdmp1#

可以使用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)
mqxuamgl

mqxuamgl2#

我相信根据接线员的优先级
问题是AND has higher precedence than OR。所以1 AND 2 OR 3等价于(1 AND 2) OR 3
作为旁注:如果使用像this one这样 Package 器,可以这样写:

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

h79rfbju3#

为什么不把它们翻过来。应等于:

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

希望我已经在上面正确设置了括号,但是你明白我的意思了。

fgw7neuy

fgw7neuy4#

这里有一个方法,它允许你在代码中使用现有的AR方法,比如where,也许还有任何现有的作用域等。因此,根据需要可以很容易地使用Arel重用现有的AR代码。

class Participant
  scope :grouped, -> {
    group1 = arel_table.grouping(where(accepted: false, contact_id: 1).arel.constraints)
    group2 = arel_table.grouping(where(id: nil).arel.constraints)

    where(group1.or(group2))
  }
end

这在Rails 7中也可以工作,也许在Rails 6.x中也可以。

相关问题