Sql 有没有办法反转ActiveRecord::关系查询?

Sql 有没有办法反转ActiveRecord::关系查询?,sql,ruby-on-rails,ruby-on-rails-3,arel,Sql,Ruby On Rails,Ruby On Rails 3,Arel,假设我们有以下几点: irb> Post.where(:hidden => true).to_sql => "SELECT `posts`.* FROM `posts` WHERE posts.hidden = 1" 我们能从中得到一个反向SQL查询吗? 我要找的可能应该是这样的: irb> Post.where(:hidden => true).invert.to_sql => "SELECT `posts`.* FROM `posts` WHERE NO

假设我们有以下几点:

irb> Post.where(:hidden => true).to_sql
=> "SELECT `posts`.* FROM `posts` WHERE posts.hidden = 1"
我们能从中得到一个反向SQL查询吗?

我要找的可能应该是这样的:

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

用不同的语法,是的。例如:

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))
通过将反向查询传递回ActiveRecord,我们可以进一步了解:

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

这将返回ActiveRecord对象,正如您通常期望的那样。

当我查找具有“not true”条件(如false或nil)的记录时,我所做的是:


在rails 4中,有用于此目的的
not
后缀:

Post.where.not(hidden: true).to_sql
# => SELECT FROM `posts` WHERE `posts`.`hidden` != 1
在rails 3中,您可以使用。它提供了许多有用的特性。用它你可以写:

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

最后,我们使用Rails 7的方法
invert_,其中

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

请检查此项以了解更多详细信息。

Hmm。对某人的评论
where(:hidden=>false)
进行错误的投票。这段代码不会生成OP所寻找的SQL类型。这与我所寻找的并不完全相同,但仍然是一个非常好的答案。您找到了其他方法吗?也许是更好的语法?答案对你有用吗?事实上,我认为这甚至是不可能的,因为我实际上要求的是反转和ActiveRecord::Relation对象,它可能有或可能没有多个连接和包含,这会使问题变得太复杂(我们应该在哪里反转,哪些不反转?)。我想我会把这件事留待答复。
irb> Post.where(:hidden => true).invert_where.to_sql
"SELECT \"posts\".* FROM \"posts\" WHERE \"posts\".\"hidden\" != 1"