Glad You're Ready. Let's Get Started!

Let us know how we can contact you.

Thank you!

We'll respond shortly.

Cacheable Flash

This post was originally written by Brian Takita.

Page caching is an easy way to get massive performance and scalability increases with little up front effort.

Of course, when page caching, a number of design changes are necessary. For example, server side session data cannot be used to render data on cached pages.

Rails provides the flash hash to easily render alert messages and errors. In the controller you can write to the flash hash:

flash[:error] = "You cannot go there"

# or

flash[:notice] = "Welcome to eternity"

and render the flash hash in the view. Typically the rendering happens on a layout:

<div id="error_div_id" class="flash flash_error"><%= flash[:error] %></div>

<div id="notice_div_id" class="flash flash_notice"><%= flash[:notice] %></div>

There are some strange quirks with using flash such as needing to use FlashHash#now when rendering the response without redirecting.

Everything works great until you need to page cache the landing page.

For example, lets say you page cache your home page. After logging in, you are redirected to the home page with the flash notice “Logged in successfully”. When page caching, this solution does not work because the request is responded to by the Web Server (i.e. Apache) and does not reach the Rails App server (i.e. Mongrel).

This means the view does not get a chance to render the flash error and notice.

There are a couple of solutions to this problem.

  • Do an AJAX request back to the server to render the flash error and notice (i.e. using RJS)
  • Send the flash error and notice from the server with cookies and render it during page load

Introducing Cacheable Flash

To solve the problem using cookies on Peer to Patent, we wrote the Cacheable Flash plugin. The plugin allows you to set the flash hash as normal on the controller. It handles converting the flash hash into cookies. All you need to do is include the CacheableFlash module into your controller.

class ApplicationController < ActionController::Base

  include CacheableFlash

  # ...


On the view side, you will need to add some javascript.

<div id="error_div_id" class="flash flash_error"></div>

<div id="notice_div_id" class="flash flash_notice"></div>

<script type="text/javascript">


  Flash.writeDataTo('error', $('error_div_id'));

  Flash.writeDataTo('notice', $('notice_div_id'));


The Flash.transferFromCookies method:

  • Grabs the flash data from the cookies and saves it to
  • Deserializes the flash hash from JSON to Javascript
  • Erases the flash data from the cookies

The Flash.writeDataTo method:

  • Writes data from the passed in key in to the passed in element or element id

Here is how the life cycle of the login works:

  1. The user enters the correct login information
  2. Rails handles the web request. In the Login controller, flash[:notice] is written to
      if current_user
        flash[:notice] = "Welcome to Eternity"
  3. An after filter serializes contents of the Flash Hash as JSON into cookies
  4. The after filter clears the flash hash
  5. The cached page is rendered
  6. The client side receives and clears the flash cookie data
  7. The client side javascript renders the flash messages

There is also a side benefit — you don’t have to use FlashHash#now because storing the flash in cookies to be rendered and erased by the client makes this unnecessary.

The Cacheable Flash plugin is on the Pivotal RB project page ( You can install it by running:

ruby script/plugin install svn://

It will copy flash.js, cookie.js, and json.js if you do not already have these files.

Happy Page Caching!!

Thanks to Josh Susser for pairing with me on this.

  1. says:

    So dumb question – but how do I do the caching part? I have some reports that take forever to run. I want to cache them overnight. At the moment I am doing it via a sloppy hack. But this post implies that rails has a builtin way?

  2. choonkeat says:

    thanks for getting to it! this community is great :-)

  3. Ismael says:

    Is’t it possible to overload flash[:something].to_s so it writes the needed Javascript for you? That way you would render the flash as usual.

  4. Brian Takita says:

    Ismael, that is an interesting idea.

    The after filter would need to be changed to generate the javascript. The client side can then eval the contents of the cookie.

    We can remove the 2 Flash.writeDataTo calls by using generating the JS using the key/value pairs in the Hash.

    Nick recommended we use convention for the element ids.
    For example, the error and notice elements would have the ids “flasherror” and “flashnotice”.

    I’d like to have the after filter generate the JS by default, and still have a hook to easily override this behavior.

  5. Brian Takita says:

    Mikey, you can use Rails standard page caching and have a cron expire the page, by deleting the page, every night.

    You can also use a cron strategy where your cron does a HTTP request and writes the output to the cached file.

  6. ml says:

    Hm, how does fallback for non-javascript browsers work?

  7. John says:

    Have you guys thought about modifying this so that you can replace any portion of the page, not just the flash, with a dynamic bit and still cache the whole page? I’m thinking of your login example, showing the logged in users name on the page somewhere as well as the flash.

  8. Brian Takita says:

    ml, there is no fallback built into the plugin.

    You could make your own fallback by extracting the JS rendering into a helper method. There can be a state that will either render using javascript or render directly on the server side.

    If you have a non-js browser, it would be difficult (I’m not saying impossible) to render dynamic content using page caching.

  9. Brian Takita says:

    John, on Peer to Patent and other projects at Pivotal, we do that by having a javascript conditional in the page.

    For example, there is the header that shows “Hello, John” when you are logged in and the Login links when you are not logged in. We need to render the html for both scenarios to page cache this.

    We a javascript conditional that looks into the cookies to see if you are currently logged in, to decide which html to show.

    This can definitely be the topic of another blog post.

    You can see more about Peer to Patent’s caching strategy at Rails, Slashdotted: no problem.

  10. Don Parish says:

    On Rails 1.2.3, I had to include the json gem in the init.rb of the plugin for it to work for me.

  11. Brian Takita says:

    Don, Thank you for the bug report. I fixed it.

  12. thomas says:

    I have used similar strategies to page cache pages and they have worked well.
    On places like the homepage I usually store the user info in a cookie and then construct the html needed on page load

  13. Chris Saylor says:

    Great plugin! I styled my flash divs so I had to hack it a bit. Set a style display: none on the divs. Then inside flash.js move the line

    element.innerHTML = unescape(content);

    inside the if([name]) statement.

    Now add after that line, still inside the if statment, the follow effect


    Now my styled flashes only show up when there is content.

  14. weepy says:

    Actually I’ve just written a plugin (called CacheBack) that has similar functionality, but is more generic – so you can cache not just the flash, but other aspects e.g. login details in the nav or show non-sensitive conexts to each logged in user.

    If anyones interested – i can make it public.


  15. jasiek says:

    How do I test this thing? It looks like after I do a get :index or whatever, the flash dictionary is emptied.

  16. Doug says:

    @weepy – I’d definitely be interested…let me know if you open it up, dougcole at gmail

  17. Brian Takita says:

    weepy – Please post the url for your plugin. I couldn’t find it.

  18. Brian Takita says:

    jasiek – I will add test helpers to the plugin soon.
    In the mean time, add this to your test or spec helper.

      def flash_cookie
        return {} unless cookies['flash']
  19. Tom says:

    I’m using the cacheable flash, and loving it, except for one thing:

    Firefox (maybe earlier versions too) and IE 6 seem reluctant to erase the cookie on the client side, so when I refresh a page, or navigate around, my flash information gets displayed for a few pages rather than just one.

    I’ve tried changing the code that erases the cookie to modify the behavior, but with no success

    Is anyone else seeing this?

  20. Tom says:

    I’m using the cacheable flash, and loving it, except for one thing:

    Firefox (maybe earlier versions too) and IE 6 seem reluctant to erase the cookie on the client side, so when I refresh a page, or navigate around, my flash information gets displayed for a few pages rather than just one.

    I’ve tried changing the code that erases the cookie to modify the behavior, but with no success

    Is anyone else seeing this?

  21. Henrik N says:

    I ran into an issue on edge Rails where one of my before filters set a flash and redirected: this would prevent the Cacheable Flash after_filter from running at all.

    My fix was simply to make Cacheable Flash use an around_filter instead (doing nothing before the yield) since these aren’t interrupted.

  22. Brian Takita says:

    Henrik, thanks for the report. I’ll add the fix.

  23. Brian Takita says:

    Tom, are you still having the issue?
    Are you doing custom things with your Rails cookies, such as changing the path?

  24. msq says:

    Thanks! Very useful plugin.

  25. Jonathan C says:

    Works like a charm, thanks so much!

  26. Bala Paranj says:


    In my application.html.erb layout I have:

    flash.each do |key,value|
    div id=”flash” class=”flash_key
    span class=”message” value span

    Should I use the flash as the value for the div id? Will it work?

  27. Brian Takita says:

    @Bala – Do you mean using the keys in your flash hash as the div id?
    There’s no reason why it wouldn’t work. The thing you may need to be concerned about is defining a flash key of an already existing id on your page.

  28. Michael Erb says:

    I added:


    to cacheable_flash.rb at line 2 so I didn’t have to change my layouts.

    Yes, I’m that lazy :o)

  29. Brian Takita says:

    @Michael – Thank you. I added your changes.

    Also, I added cacheable-flash to github.


  30. Lee Fyock says:

    We’re seeing the same issue (I believe) as Tom with IE6 — the flash hangs around for a few page loads after it should have gone away.

    Also, it’s fairly easy to get the flash to concatenate messages on successive page loads, rather than clearing the flash between page loads. Just post form data a couple of times before the entire page has time to load.

    So, on our login page, if you just hit return without putting in a name and password, you see “Invalid user/password combination”. Hit return again, and the flash now says “Invalid user/password combinationu003Cbr/u003EInvalid user/password combination”. Keep hitting return, and they keep concatenating. If you allow the page to completely load, then you’re OK.

    This is reproducible in FF3 for Mac, Safari for Mac, and IE7, at least.

    Does anyone have any ideas on how to prevent this?

    Does anyone have any ideas on the IE6 issue?


Post a Comment

Your Information (Name required. Email address will not be displayed with comment.)

* Copy This Password *

* Type Or Paste Password Here *