I'm trying to query the equivalent of this sql snippet using arel:
WHERE (("participants"."accepted" = 'f' AND "participants"."contact_id" = 1)
OR "participants"."id" IS NULL)
So I want (accepted && contact_id=1) OR NULL
Here's what I've got in AREL
participants[:accepted].eq(false).and(participants[:contact_id].eq(1).
or(participants[:id].is(nil)
Problem is, this generates:
("participants"."accepted" = 'f' AND "participants"."contact_id" = 1 OR "participants"."id" IS NULL)
Note the lack of parentheses around my and conditions. I believe that according to the operator precedence, that I'm getting:
accepted && (contact_id=1 OR NULL)
Adding parentheses in in the AREL query has no affect. Any thoughts?
I believe that according to the operator precedence
The problem is that AND has higher precedence than OR. So 1 AND 2 OR 3
is equivalent to (1 AND 2) OR 3
.
As a side note: if you use a wrapper like this one, you can write:
User.where((User[:created_at] > 3.days.ago) & (User[:enabled] == true))
You can generate parentheses using 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)
Why not flip them around. Should be equivalent to:
participants[:id].is(nil).or(participants[:accepted].eq(false).and(participants[:contact_id].eq(1))
hopefully I've got the parens properly set in the above, but you see what I mean...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With