问题
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