I have the following example query:
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>]
However running:
p items.count
Results in NoMethodError: undefined methodmap’ for Arel::Nodes::SqlLiteral`
I appreciate the query is silly, however the non-simplifieid query is a bit too complicated to copy and this was the smallest crashing version I could create. Any ideas?
Can you call
allon that object to essentially cast it to an Array?Or perhaps in that case,
sizewould be more appropriate. In any case, this will execute the query and load all the objects into memory, which may not be desirable.It looks like the problem is with your
includes([:images]). On a similar application, I can execute this from the console:(Notice that the
countoverrides the SELECT clause, even though I explicitly specifieditems.*. But they’re still equivalent queries.)As soon as I add an
includesscope, it fails:I tried a few different means of acquiring the count, like
select('COUNT(categories.*)'), but they all failed in various ways. ActiveRecord seems to be falling back on a basic LEFT OUTER JOIN to perform the eager loading, possibly because it thinks you’re using some kind of condition or external table to perform the join, and this seems to confuse its normal methods of performing the count. See the end of the section on Eager Loading in theActiveRecord::Associationsdocs.My Suggestion
If the join doesn’t affect the number of rows returned in the outer query, I’d say your best bet is to execute one query to get the count and one query to get the actual results. We have to do something similar in our application for paging: one query returns the current page of results, and one returns the total number of records matching the filter criteria.