Is there a way to invert an ActiveRecord::Relation query?

放肆的年华 提交于 2019-12-03 06:00:17

With a different syntax, yes. Example:

posts = Post.scoped.table # or Arel::Table.new("posts")
posts.where(posts[:hidden].eq(true).not).to_sql
# => SELECT  FROM `posts` WHERE NOT ((`posts`.`hidden` = 1))

In rails 4 there is not suffix for this purpose:

Post.where.not(hidden: true).to_sql
# => SELECT FROM `posts` WHERE `posts`.`hidden` != 1

In rails 3 you can use squeel gem. It gives many usefull features. And with it you can write:

Post.where{ hidden != true }.to_sql
# => SELECT FROM `posts` WHERE `posts`.`hidden` != 1
sunaku

We can take Zabba's answer further by passing the inverted query back into ActiveRecord:

table = Post.arel_table
query = table[:hidden].eq(true).not # the inverted query, still ARel
Post.where(query) # plug it back into ActiveRecord

This will return ActiveRecord objects, as you would normally expect.

What I do when I'm looking for records with a "not true" condition (eg, false or nil) is:

Post.where(["(hidden IS NULL) OR (hidden = ?)", false])
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!