条件使用NOT NIL的Rails

时间:2010-11-23 02:56:02

标签: ruby-on-rails rails-activerecord arel

使用rails 3样式我将如何写出相反的内容:

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

我想找到id不是零的地方。我试过了:

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

但是回归:

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

这绝对不是我所需要的,而且几乎看起来像是ARel中的一个错误。

5 个答案:

答案 0 :(得分:493)

使用Rails 3执行此操作的规范方法:

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

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

答案 1 :(得分:250)

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

你想要的是:

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

答案 2 :(得分:36)

对于Rails4:

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

  Foo.joins(:bar)

  Select * from Foo Inner Join Bars ...

但是,对于记录,如果你想要一个“NOT NULL”条件,只需使用not predicate:

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)
  

弃权警告:看起来你急于装桌子(一个   of:....)在字符串SQL片段中引用。例如:

Post.includes(:comments).where("comments.title = 'foo'")
     

目前,Active Record识别字符串中的表,并且知道   将评论表加入查询,而不是加载评论   在单独的查询中。然而,这样做没有写完全   SQL解析器本质上是有缺陷的。因为我们不想写SQL   解析器,我们正在删除此功能。从现在开始,你必须   当您从a引用表时,显式地告诉Active Record   字符串:

Post.includes(:comments).where("comments.title = 'foo'").references(:comments)

答案 3 :(得分:22)

不确定这是否有用,但这对我在Rails 4中起作用

Foo.where.not(bar: nil)

答案 4 :(得分:21)

使用Rails 4很容易:

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

另见:     http://guides.rubyonrails.org/active_record_querying.html#not-conditions