Cache is running query on view fragment cache hit anyway

I’ve been developing with Rails for a few years now, but one part I haven’t used is view fragment caching.

I’m using it now, and I’m seeing what I think is undesirable behavior, but I need someone with experience to tell me if it’s supposed to be this way.

I’m caching a collection, and it runs the query to generate the cache key (count, max updated_at) as expected, but then regardless of whether there is a cache hit, it still runs the main query, and if there are includes, it runs those queries, too. If the view fragment is being served from the cache, then those queries are just wasted time. Has it always been like this?

I can work around it by using “<% cache @collection.cache_key do %>” instead of “<% cache @collection do %>”, but it seems like it shouldn’t run the query in the first place.

Yeah, I created a Rails 3 and Rails 4 project. Rails 3 doesn’t support #cache_key on collection, and Rails 4 uses each individual element to create a cache key.

I set up byebug and traced the #cache view helper. The reason the relation is being loaded is because the helper eventually calls #to_a on the relation, which of course results in the query being executed.

Looks like the best solution is using #cache_key directly.

Possibly related: Rails 5 has new (improved) behaviour for collection caching

<%= render partial: :post, collection: @posts, cached: true %>

will cache

although

<%= collection: @posts, cached: true %>

will not cache

more info on how it works and the benefits here: