Ошибка метода «map» для # <Arel :: Nodes :: SqlLiteral> - PullRequest
3 голосов
/ 16 февраля 2012

У меня есть следующий пример запрос:

source = "(SELECT DISTINCT source.* FROM (SELECT * FROM items) AS source) AS items"
items = Item.select("items.*").from(source).includes([:images])
p items # [#<Item id: 1>, #<Item id:2>]

Однако работает:

p items.count 

Результаты в NoMethodError: undefined method map 'для Arel :: Nodes:: SqlLiteral`

Я считаю, что запрос глупый, однако запрос не-упрощения слишком сложен для копирования, и это была самая маленькая сбойная версия, которую я мог создать.Есть идеи?

Ответы [ 2 ]

4 голосов
/ 16 февраля 2012

Можете ли вы вызвать all для этого объекта, чтобы по существу привести его к массиву?

Item.select("items.*").from(source).includes([:images]).all.count

Или, возможно, в этом случае size будет более подходящим.В любом случае это выполнит запрос и загрузит все объекты в память, что может быть нежелательно.


Похоже, проблема в вашем includes([:images]).В аналогичном приложении я могу выполнить это из консоли:

> Category.select('categories.*').from('(SELECT DISTINCT source.* FROM (SELECT * FROM categories) AS source) AS categories').count
  (0.5ms)  SELECT COUNT(*) FROM (SELECT DISTINCT source.* FROM (SELECT * FROM categories) AS source) AS categories

(Обратите внимание, что count переопределяет предложение SELECT, хотя я явно указал items.*. Но они по-прежнему эквивалентны запросам.)

Как только я добавляю область действия includes, она выходит из строя:

> Category.select('categories.*').from('(SELECT DISTINCT source.* FROM (SELECT * FROM categories) AS source) AS categories').includes(:projects).count
NoMethodError: undefined method `left' for #<Arel::Nodes::SqlLiteral:0x131d35248>

Я попробовал несколько различных способов получения счетчика, например select('COUNT(categories.*)'), но все онине удалось по-разному.ActiveRecord, похоже, использует базовый LEFT OUTER JOIN для выполнения активной загрузки, возможно, потому, что он думает, что вы используете какое-то условие или внешнюю таблицу для выполнения соединения, и это, кажется, путает его обычные методы выполнения подсчета,См. Конец раздела «Стремительная загрузка» в ActiveRecord::Associations документах .

Мое предложение

Если объединение не влияет на количество строк, возвращаемых ввнешний запрос, я бы сказал, что вам лучше всего выполнить один запрос для подсчета и один запрос для получения фактических результатов.Мы должны сделать нечто подобное в нашем приложении для подкачки страниц: один запрос возвращает текущую страницу результатов, а другой возвращает общее количество записей, соответствующих критериям фильтра.

2 голосов
/ 25 октября 2016

Проблема в Rails # 24193 https://github.com/rails/rails/issues/24193 и связана с from в сочетании с активной загрузкой. Обходной путь должен использовать форму: Item.select("items.*").from([Arel.sql(source)]).includes([:images])

...