Dwight Watson's blog

Rendering collections in Rails, with custom cache parameters

April 19, 2021

Rails has a simple syntax for rendering a collection of partials and caching them all in one go. Under the hood it'll try and fetch all the cached views at once, minimising unnecessary I/O.

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

This works well, but what happens if the partial cache depends on additional data? For example - if something was specific to the logged in user. Generally you'd instead handle this with the cache helper in the partial instead.

<%= cache [post, current_user] do %>

Unfortunately this means you'll need to hit your cache store for each individual partial which is not as performant.

I've long looked for a way to solve this but couldn't find the solution. It didn't appear to be documented anywhere, until I stumbled across it in the cache helper's source code.

You can actually pass a proc to the cached argument and control the cache constraints from the top render` call!

<%= render collection: @posts, partial: "posts/post", cached: -> (post) { [post, current_user] } %>

Just like that you get the performance benefits of a single cache hit and don't need to dirty your partials with manual cache calls.

A blog about Laravel & Rails by Dwight Watson;
developer of Roomies.com, myRent.co.nz & StudentVIP.com.au.

Follow me on Twitter, or GitHub.