What I want to express is this:
Model.where("a IS NOT NULL `**`OR`**` b IS NOT NULL")
In Rails 4, where.not clause is enabled:
Model.where.not(a: nil, b: nil)
However, This expression equals
Model.where("a IS NOT NULL `**`AND`**` b IS NOT NULL")
How can I express
"a IS NOT NULL `**`OR`**` b IS NOT NULL"
with where.not clause?
You could create your query as you've tried with where.not for the a and b attribute:
query = Model.where.not(a: nil, b: nil)
And then use inject in the where values for the query created before by passing the or operator:
Model.where(query.where_values.inject(:or))
This will give you a query like:
SELECT "model".*
FROM "model"
WHERE (
"model"."a" IS NOT NULL OR
"model"."b" IS NOT NULL
)
Despite of the first one which gives you something using the AND operator, like:
SELECT "model".*
FROM "model"
WHERE ("model"."a" IS NOT NULL) AND
("model"."b" IS NOT NULL)
where.not with multiple attributes!Up to Rails 5.2, if we use where.not with multiple attributes, it applies logical NOR (NOT(A) AND NOT(B)) in WHERE clause of the query.
Post.where.not(source_type: "Feed", source_id: 100).to_sql
# => SELECT "posts".* FROM "posts" WHERE "posts"."source_type" != 'Feed' AND "posts"."source_id" != 100
Rails 6 adds a deprecation warning.
Post.where.not(source_type: "Feed", source_id: 100)
DEPRECATION WARNING: NOT conditions will no longer behave as NOR in Rails 6.1.
To continue using NOR conditions, NOT each conditions manually
(`.where.not(:source_type => ...).where.not(:source_id => ...)`).
Rails 6.1+ will change where.not working to NAND (NOT(A) OR NOT(B)).
Post.where.not(source_type: "Feed", source_id: 100).to_sql
# => SELECT "posts".* FROM "posts" WHERE ("posts"."source_type" != 'Feed' OR "posts"."source_id" != 100)
Sources:
There is no rails-way to do this in rails 4.
You could try rails_or which give you or and or_not method:
Model.where.not(a: nil).or_not(b: nil)
Or upgrade to rails 5 and write the query as:
Model.where.not(a: nil).or(Model.where.not(b: nil))
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