---
title: All the kings horses
teaser:
tags: web,rails
author: Matt Jankowski
published_on: 2007-09-27
---

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...

    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](http://images.thoughtbot.com/ui/2007-9-27-ProfitCash-lrg.jpg) flash on
the page when you didn't expect to.

Instead of `flash[:failure]`, use `flash.now[:failure]`...

      ...
      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 &mdash; 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
