382

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

それは間違いなく私が必要としているものではなく、ほとんど ARel のバグのようです。

4

5 に答える 5

541

レール 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))

レール3

Rails 3 でこれを行う標準的な方法は次のとおりです。

Foo.includes(:bar).where("bars.id IS NOT NULL")
于 2010-11-23T03:51:48.913 に答える
252

これは ARel のバグではなく、ロジックのバグです。

ここで必要なのは次のとおりです。

Foo.includes(:bar).where(Bar.arel_table[:id].not_eq(nil))
于 2010-11-23T03:53:14.203 に答える
38

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)

非推奨警告: 文字列 SQL スニペットで参照されているテーブル (次のいずれか: ....) を積極的にロードしているようです。例えば:

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

現在、Active Record は文字列内のテーブルを認識し、別のクエリでコメントをロードするのではなく、コメント テーブルをクエリに JOIN することを認識しています。ただし、本格的な SQL パーサーを作成せずにこれを行うと、本質的に欠陥があります。SQL パーサーを書きたくないので、この機能を削除します。これからは、文字列からテーブルを参照するときは Active Record に明示的に伝える必要があります。

Post.includes(:comments).where("comments.title = 'foo'").references(:comments)
于 2013-10-06T18:36:25.630 に答える
36

これが役立つかどうかはわかりませんが、Rails 4でうまくいったのはこれです

Foo.where.not(bar: nil)
于 2016-11-11T12:03:01.923 に答える
23

Rails 4 では簡単です。

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

参照: http://guides.rubyonrails.org/active_record_querying.html#not-conditions

于 2014-08-08T06:12:36.657 に答える