使用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中的一个错误。
答案 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