One small annoyance about working with the flash in Rails is that it only works well if you render separate pages per action. The flash falls apart if you do an Ajax call and render an RJS template or some inline javascript. The flash won't show up when it should, and it'll show up on some other page when you don't want it to. I made 2 small changes to my app to make flash behave better when an Ajax call is made.
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 render :update
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
after_filter
to ApplicationController
to
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.