提问



使用rails 3样式我怎么写相反的:


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


我想找到id为非null的地方。我试过了:


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


但那会回来:


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


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

最佳参考


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


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


ActiveRecord 4.0及以上添加where.not所以你可以这样做:[20]


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


在使用表之间的范围时,我更喜欢利用merge,以便我可以更轻松地使用现有范围。[21]


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


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


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


我不再建议使用Squeel,因为它不总是有一个全职维护者,它依赖于导致频繁破坏变化的私有API。[24]

其它参考1


它不是ARel的一个错误,它是你逻辑中的一个错误。


你想要的是:


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

其它参考2


对于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


使用Rails 4很容易:


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


也可以看看:
    http://guides.rubyonrails.org/active_record_querying.html#not-conditions[25]

其它参考4


不确定这有用,但这对我在Rails 4中有用


Foo.where.not(bar: nil)