24

When you use caches_action :layout => false in Rails 3, any content_for blocks that are populated in the cached view and used in your layout wind up empty. Is there any workaround for this?

E.g. in my application I have the following rather typical setup.

A helper method called from my views which sets the page title:

# application_helper.rb
def page_title(title)
    content_for(:page_title) { title }
end

A line in my layout file as follows

# application.html.erb
<head>
<title><%= yield(:page_title) %></title>
</head>

And in a view I might call

# index.html
<% page_title 'Hello!' %>

Of course, if you cache your action with :layout => false, this results in having blank page titles, since action caching ignores all content_for blocks.

Is there no workaround for this? Action caching with :layout => false is so close to being brilliantly useful, but this glitch renders it quite awkward.

Other folks asking or commenting about this same issue:

  1. http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/d8d72f050701d44b
  2. http://www.golygon.com/2011/04/tips-and-tricks-in-ruby-on-rails/
  3. https://rails.lighthouseapp.com/projects/8994/tickets/4140-action-caching-with-caches_action-and-layout-false

And the Rails documentation that notes this behavior:

"WARNING: content_for is ignored in caches. So you shouldn’t use it for elements that will be fragment cached."

cailinanne
  • 8,332
  • 5
  • 41
  • 49

2 Answers2

2

I believe the way I got around this was to create a fragment cache of the parts of the header that are dependent on the content_for being populated.

so it looks something like this:

# application.html.erb
<head>
<% cache("#{request.env['PATH_INFO']}/header") do %>
    <title><%= yield(:page_title) %></title> 
<% end %>

so this cached fragment should be populated at the same time the action is cached.

Andrew Wright
  • 116
  • 1
  • 4
  • 2
    Don't do this, the two caches (action and your fragment) won't necessarily always be there, depending on your cache store. One might be pushed out of the cache or expired sooner. I am still looking for a good solution to this, though. What i'm doing now is patching the action caching to store these things such as title, etc in a hash, marshalling it, and caching that whole thing. HOWEVER this fails occasionally, and is driving me absolutely insane. – XP84 Jun 09 '12 at 05:35
  • Yes this is an important point, I currently use the file cache store and as such the two caches are stored in the same directory and I wipe the whole directory at once when clearing the cache for a record. – Andrew Wright Jul 11 '12 at 18:45
0

I had exactly the same problem and used this gist and it works fine!

Christoffer
  • 2,271
  • 3
  • 26
  • 57