Часть запроса может быть выполнена довольно просто с помощью области:
class Category
scope :grouped_entries, lambda { |user, date|
select(['categories.*', 'COUNT(entries.id) as count_entries'])
.joins(:entries)
.where('entries.user_id = ?', user.id)
.where('MONTH(entries.created_at) = ?', date.month)
.group('categories.id')
}
end
Который затем может быть зациклен:
<% Category.grouped_entries(current_user, Date.today).each do |category| %>
<%= category.name %> with <%= category.count_entries %> entries this month.
<% end %>
Конечно, для кеширования необходимо обновлять кеш каждый раз, когда в этом месяце создается запись. Например, вы можете кэшировать запрос следующим образом:
@categories = Rails.cache.fetch("/grouped_entries/#{current_user.id}/#{Date.today.month}") do
Category.grouped_entries(current_user, Date.today).all
end
А затем просто истекает срок его действия, когда создается новая запись с использованием user_id и записи creation_at month. Я бы сказал, что вы должны использовать этот подход, прежде чем пытаться кэшировать записи каждой отдельной категории в отдельности. Этот запрос должен выполняться довольно быстро, поэтому вам не нужно углубляться в кеширование каждой строки в отдельности. Он также будет выполнять один запрос, а не один для каждой категории.
Вот почему я бы не кэшировал каждую строку отдельно:
- Вам все еще нужно запросить базу данных, чтобы получить список категорий или идентификаторов категорий для пользователя, поэтому вам все равно придется выполнить один запрос.
- Истечение срока действия Cachine более сложное, потому что есть больше случаев, когда вам нужно завершить срок действия двух кешей, например, когда изменяется категория для записи, вы должны истечь старый кеш категории и новый кеш категории.
- Вы можете выполнить больше запросов к вашей базе данных, чтобы получить информацию о кеше с истекшим сроком действия, и задержка для базы данных, вероятно, займет больше времени, чем фактический запрос.
- Вам не нужно кэшировать каждую строку, потому что запрос прост и использует индексы. У вас должен быть индекс user_id и category_id для записей.