The first trick is something I learned at work. First, we need to extract the rendering of the flash into a partial in 'app/views/layouts/_flash.html.erb'. This will allow us to render the flash in a normal template, but also allow us to replace the flash in an inline render. In my main template, I do a normal:
<div id="flash_messages"> <%= render :partial => 'layouts/flash' %> </div>
To refresh the flash when an Ajax request happens, I add a 'reload_flash' method to ApplicationHelper:
def reload_flash page.replace "flash_messages", :partial => 'layouts/flash' end
Then from my RJS templates or from a
block, I can call the reload_flash to refresh the flash inline:
# within a controller action render :update do |page| flash[:notice] = "Entering 'beast mode'..." page.reload_flash end
This all seems fine and dandy until you visit another page.
Unfortunately, the flash is not cleared because you haven't visited
another action, so you end up with the flash message redundantly
displaying a 2nd time. To fix this, I added an
clear the flash after an action if it was an Ajax request:
class ApplicationController < ActionController::Base after_filter :discard_flash_if_xhr protected def discard_flash_if_xhr flash.discard if request.xhr? end end
Easy isn't it? The catch here is to remember to call
reload_flash whenever you're doing an inline render.
Another useful tip plugin for working with the flash is the flash-message-conductor plugin. I use it to controll the logic of when to show the flash, and also control some animations for hiding and showing the flash. It's a nice simple plugin.