Welcome to Giant Robots Smashing Into Other Giant Robots — a weblog about development, business, design and technology — written by thoughtbot.
All the kings horses
When you get a report from your site users or your clients complaining about seeing flash messages twice or seeing a flash message on the incorrect page, don’t listen to your coworker/boss when they tell you it must be a rails bug. It’s a feature.
When you do this…
1 2 3 4 5 6 7 8 9 10 |
def update @user = User.find params[:id] if @user.update_attributes params[:user] flash[:success] = 'User attributes have been updated' redirect_to user_path(@user) else flash[:failure] = 'Could not save user.' render :action => :edit end end |
...that flash[:failure] call you’re making is going to leave the flash set for the next request to display.
Now, since you’re rendering the edit view, which is probably a form that’s going to display some errors and POST right back to #update, you might not find this in “normal” application use. But if you want to see it, you can probably just click away from that edit page to some other link, and then you’ll see your “failure” flash on the page when you didn’t expect to.
Instead of flash[:failure], use flash.now[:failure]...
1 2 3 4 |
...
flash.now[:failure] = 'Could not save user.'
render :action => :edit
... |
You still access its value via flash[:failure] from your views, but it will get removed on the page render, rather than on the next request, which is what you want because you don’t want to keep it around for the next request.
From the rails docs…
This method enables you to use the flash as a central messaging system in your app. When you need to pass an object to the next action, you use the standard flash assign ([]=). When you need to pass an object to the current action, you use now, and your object will vanish when the current action is done.
One downside to this is you can’t do…
assert_equal 'Could not save user.', flash[:failure] |
...in your functional tests anymore — because after the view is processed and your functional test is running, that value is already gone! Instead, you can use…
assert_select 'div.flash-failure p', 'Could not save user.' |
...which will check that the view had a p element, surrounded by a div with the right class, where the p has your well written save failure copy contained in it.
So the rule is…
- Use flash when you’re going to redirect, so that the next action will be able to display the flash value
- Use flash.now when you’re going to render, so that the current view can display the value and the next view won’t (additionally and wrongly) display it.
Additional rules to keep in mind…
- Use the flash at the top of a page to tell someone THAT they are not fit to be using your app
- Use error_messages_for down in the view to tell them WHY they are not fit to be using your app
About this entry
You're reading an entry on GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS, the company weblog of thoughtbot, inc.
- Author:
- Matt Jankowski
- Published:
- September 27th 06:10 PM
- Updated:
- September 28th 09:39 AM
- Sections:
- Development
thoughtbot is hiring
We are hiring web developers and web designers in both Boston and New York, NY.
What are we up to?
We built Shoulda, an eclectic set of additions to Test::Unit; Paperclip to manage uploaded files without hassle; Jester, a REST/ActiveResource client library written in Javascript, and Squirrel, an enhancement for ActiveRecord's find syntax; — amongst some other projects.

Chad (President) and Jon (CTO) co-authored a technical book titled Pro Active Record: Databases with Ruby and Rails, which explores the ins and outs of the ActiveRecord ruby library. You can buy it today at Amazon.com.
About thoughtbot, inc.
We are a small web application development consulting business, with offices in Boston, MA and New York, NY. If you're looking to find a team for your next web development project or your new web application — get in touch.
8 comments
Jump to comment form