Начинаю думать, что это невозможно... Так как в calculate.rb, в методе execute_grouped_calculation есть такой блок:
if association
key_ids = calculated_data.collect { |row| row[group_aliases.first] }
key_records = association.klass.base_class.find(key_ids)
key_records = Hash[key_records.map { |r| [r.id, r] }]
end
то есть, для калькуляции, после самого запроса, rails получает только те записи, которые соответствуют первому полю из тех, по которым была группировка
includes и preload добавляют join к первому запросу, но, так как этих полей нет в select (да и при добавлении их туда ничего не происходит), то при обращении к категории заново идет запрос к базе.
Буду еще пытаться, но видимо придется после запроса самому собирать все shop.category_id и самому делать по ним запрос
В итоге сделал вот так:
purchases = user.purchases.select('shop_id, sum(count)').group(:shop_id)
shop_ids = purchases.collect do |purchase| purchase.shop_id end
shops = Shop.includes(:category).find(shop_ids)
Но все равно полагаю, что должен быть способ сделать это более правильно.