Jonathan Bennett

Let Rails Help You – Now With Caching

Thoughtbot recently published a great article on building a favouriting system in Rails using standard conventions. I built almost the exact same thing for a client two weeks ago. This is one of the reasons Rails is so great: developers are naturally encouraged to write similar code to solve similar problems. But there’s one place their implementation could trip you up: caching.

As written, their _note partial would run into issues if you’re caching it. The naive implementation renders the favourite button for User A, caches it, and then shows that same button to User B. Unless your users like seeing each other’s favourites, this is a problem.

In my implementation, the cached partial renders a turbo_frame that will dynamically show the appropriate create/destroy button:

<!-- app/views/notes/_note.html.erb -->
<%= render 'favorite_records/loader', favoritable: note %>

<!-- app/views/favorite_records/_loader.html.erb -->
<%= turbo_frame_tag dom_id(favoritable, :favorite),
                    src: favorite_record_path(favoritable.favoritable_sgid) %>
                    
<!-- app/views/favorite_records/show.html.erb -->
<%= turbo_frame_tag dom_id(@favoritable, :favorite) do %>
  <%= render 'application/favorite_record_button', favoritable: @favoritable %>
<% end %>

By matching the ids on the turbo frames, the content from the show action will dynamically replace the button on the note partial, bypassing the cache entirely.

This approach sticks to Rails conventions while sidestepping the caching pitfalls — so you get both speed and accuracy.

Caching bugs are tricky and easy to miss — but they don’t have to be.

If you’re running into similar issues, reply and tell me what you’re stuck on. I might write up a fix that helps you out.