Rails的条件使用非空

使用rails 3风格,我将如何写相反的:

Foo.includes(:bar).where(:bars=>{:id=>nil})

我想找到id不为nil的地方。我试着:

Foo.includes(:bar).where(:bars=>{:id=>!nil}).to_sql

但结果是:

=> "SELECT     \"foos\".* FROM       \"foos\"  WHERE  (\"bars\".\"id\" = 1)"

这绝对不是我需要的,几乎看起来像一个bug在ARel。

275937 次浏览

Rails 4 +

ActiveRecord 4.0及以上版本添加了where.not,所以你可以这样做:

Foo.includes(:bar).where.not('bars.id' => nil)
Foo.includes(:bar).where.not(bars: { id: nil })

当使用表之间的作用域时,我更喜欢利用merge,这样我就可以更容易地使用现有的作用域。

Foo.includes(:bar).merge(Bar.where.not(id: nil))

此外,由于includes并不总是选择连接策略,所以在这里也应该使用references,否则可能会得到无效的SQL。

Foo.includes(:bar)
.references(:bar)
.merge(Bar.where.not(id: nil))

Rails 3

Rails 3的规范方法是:

Foo.includes(:bar).where("bars.id IS NOT NULL")

这不是ARel中的错误,而是逻辑中的错误。

你想要的是:

Foo.includes(:bar).where(Bar.arel_table[:id].not_eq(nil))

Rails4:

所以,你想要的是一个内部连接,所以你应该只使用joins谓词:

  Foo.joins(:bar)


Select * from Foo Inner Join Bars ...

但是,为了记录,如果你想要一个“NOT NULL”条件,只需使用NOT谓词:

Foo.includes(:bar).where.not(bars: {id: nil})


Select * from Foo Left Outer Join Bars on .. WHERE bars.id IS NOT NULL

注意,这个语法报告了一个弃用(它谈论的是一个字符串SQL片段,但我猜哈希条件在解析器中被更改为字符串?),所以一定要在结尾添加引用:

Foo.includes(:bar).where.not(bars: {id: nil}).references(:bar)

弃用警告:它看起来像你急于加载表(s)(一个 的:....),在字符串SQL片段中引用。例如:< / p >

Post.includes(:comments).where("comments.title = 'foo'")
当前,活动记录识别字符串中的表,并且知道 将注释表连接到查询,而不是加载注释 在一个单独的查询中。但是,这样做不需要编写一个完整的 SQL解析器本身就有缺陷。因为我们不想写SQL 解析器,我们正在删除这个功能。从现在开始,你必须 类中引用表时显式地告诉活动记录 字符串:< / p >
Post.includes(:comments).where("comments.title = 'foo'").references(:comments)

Rails 4很简单:

 Foo.includes(:bar).where.not(bars: {id: nil})
< p >参见: http://guides.rubyonrails.org/active_record_querying.html#not-conditions < / p >

不确定这是有用的,但这是我在Rails 4工作

Foo.where.not(bar: nil)