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

拟墨画扇 提交于 2019-12-04 10:32:27

问题


Let's say we have the following:

irb> Post.where(:hidden => true).to_sql
=> "SELECT `posts`.* FROM `posts` WHERE posts.hidden = 1"

Could we somehow get an inverted SQL query out of it?

What I am looking for, should probably look like this:

irb> Post.where(:hidden => true).invert.to_sql
=> "SELECT `posts`.* FROM `posts` WHERE NOT (posts.hidden = 1)"

回答1:


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))



回答2:


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



回答3:


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.




回答4:


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])


来源:https://stackoverflow.com/questions/5302510/is-there-a-way-to-invert-an-activerecordrelation-query

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