I previously discussed the difference between flash.now[:notice] and flash[:notice]. I ended with a summarizing rule that says when you end an action with render, you generally want to use flash.now[:notice], and when you end an action with redirect, you want to use flash[:notice]. While simple, I hate remembering that rule, and what really complicates things is request.xhr?
# Toward the end of an action in a controller if request.xhr? flash.now[:notice] = "Action Completed" else flash[:notice] = "Action completed." end
An Ajax Request (XHR) always should use flash.now. Why? Because if it's an ajax request, then the page was not reloaded, which means if you set flash[:notice], whatever request comes next from the user, will load with the flash[:notice] of the last request, which in this case, is an XHR request - in short, they will see a persistent, non-relevant, flash[:notice] from the ajax call. So the rule for choosing whether to use flash.now or flash becomes: If an action is a response to an ajax request, or if it ends with a render, use flash.now, otherwise use flash.
But That's Complicated!
True, it is complicated and requires a lot of conditional logic in your controllers. The truth is, the choice between flash and flash.now should be abstracted out. A controller should not be responsible for choosing whether to flash or flash.now.
set_flash
In application.rb define the following function.
def set_flash(options={}) now = options[:now] || (request.xhr? ? true : false) if now flash.now[:notice] = options else flash[:notice] = options end end
A simple, but powerful and helpful function. Instead of having to call flash.now or flash, you can just do this in your controllers (as opposed to the example above).
# Towards the end of an action in a controller set_flash :text => "Action Completed"
See, no more checks for request.xhr? because set_flash has that check. Of course, you can easily override that if you wanted an xhr request to flash and not flash.now.
set_flash :text => "Action Completed", :now => true
What I really love about the set_flash method is the ability to nicely constructed flash's with a lot of meta data:
set_flash :klass => "error", :text => "Registration failed", :alt => "Did you fill out the form correctly?"
I can then build a helper method in application_helper.rb to print out a formatted flash
def formatted_flash " <h2 class=\"#{flash[:notice][:klass] || "success"}\">#{flash[:notice][:text]}<span>#{flash[:notice][:alt]}</span></h2> " end
Obviously, you can customize this method to handle a lot of how to format the flash message logic and you can add your keys to your flash[:notice], like type (a flash isn't always a notice, maybe it's a warning). Don't settle for an unintelligent, string-based flash notice.
Excuse the shoddy formatting above, I'm working on it
Trackbacks & Pingbacks 1
[…] do some awesome things with xml and json that I will touch on in later posts. Let’s just say that set_flash loves render_either. Any […]
Post a Comment