Рельсы, где условие с использованием NOT NIL

Используя стиль rails 3, я бы написал противоположность:

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

Я хочу найти, где идентификатор не ноль. Я старался:

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

Но это возвращает:

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

Это определенно не то, что мне нужно, и почти похоже на ошибку в ARel.

+346
источник поделиться
5 ответов

Канонический способ сделать это с 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 includes не всегда выбирают стратегию присоединиться, вы должны использовать references здесь, а также, в противном случае вы можете в конечном итоге с недопустимой SQL.

Foo.includes(:bar)
   .references(:bar)
   .merge(Bar.where.not(id: nil))
+493
источник

Это не ошибка в AREL, это ошибка в вашей логике.

Здесь вы хотите:

Foo.includes(:bar).where(Bar.arel_table[:id].not_eq(nil))
+250
источник
другие ответы

Связанные вопросы


Похожие вопросы

Для Rails4:

Итак, то, что вы хотите, является внутренним соединением, поэтому вам действительно нужно использовать предикат объединения:

  Foo.joins(:bar)

  Select * from Foo Inner Join Bars ...

Но для записи, если вы хотите условие "NOT NULL", просто используйте не предикат:

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 парсер, мы удаляем эту функциональность. Отныне вы должны явно указывать Active Record, когда вы ссылаетесь на таблицу из строка:

Post.includes(:comments).where("comments.title = 'foo'").references(:comments)
+36
источник

Не уверен, что это полезно, но это то, что сработало для меня в Rails 4

Foo.where.not(bar: nil)
+22
источник

С Rails 4 легко:

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

См. также:   http://guides.rubyonrails.org/active_record_querying.html#not-conditions

+21
источник

Посмотрите другие вопросы по меткам или Задайте вопрос