views:

88

answers:

3

So, I'd like to be able to display both a flash[:notice] and a flash[:error] on the same action, but I'd like for the :notice to always be displayed above (or before) the error. Is there a way to do this?

In my controller, I thought I could just code the flash[:error] before the flash[:notice], so that rails will display it correctly, and it does a vast majority of the time. But every now and then they are randomly switched, and I can't seem to figure out why. So, how can I ensure that a flash[:notice] is always displayed above an :error ?

Edit: Thanks to Ben's and Ryan's advice, I've now just set up conditionals in my layout/application file.

    <% if flash[:notice] %>
        <div id="flash_notice"><%= flash[:notice] %></div>
    <% end %>

    <% if flash[:error] %>
        <div id="flash_error"><%= flash[:error] %></div>
    <% end %>

I'm pretty satisfied with this, but maybe there's an even better way?

Edit #2: Yes, there is. Ben added it to his answer below. Thanks again Mr. Ben.

+3  A: 

The order of display simply depends on your view code. If you do this in your controller:

flash[:notice] = "Notice me"
flash[:error] = "BAAAAADDDD"

And this in your view:

<p><%= flash[:notice] %></p>
<p><%= flash[:error] %></p>

the :notice will always appear first.

Try this for a more elegant approach. The order you define in the array is the order they'll appear in:

<% [:error, :notice].each do |condition| %>
  <%= "<p class='#{condition.to_s}'>#{flash[condition]}</p>" if flash.has_key?(condition) %>
<% end %>
Ben
Thanks Ben. I had just been relying on the code I defined in the application layout (code similar to what Ryan Bigg pointed out below). Didn't know I could specify their order for a specific view like that, in addition to the general code in the app layout. Thank you again Mr. Ben.
GoodGets
Edit: I didn't mean in addition to the general code in the layout/app file. I had just been using what Ryan Bates's nifty_layout generated. Instead I've now just defined the flashes as you have above, along with their appropriate CCS id's. Also, I had to include conditionals for when the flashes are empty. I added the code to my question in case there's a better way. Thank you again.
GoodGets
There's definitely more sophisticated ways of doing it--I just wanted you to get the nut of the idea. I'll add something to my answer to get you started.
Ben
That's much too elegant and clean. I prefer my code more clunky and cumbersome. j/p, thank you big time Ben, and I now understand flashes quite a bit better as well, much appreciated.
GoodGets
+1  A: 
Always nil your notice and error object.

<% if flash[:notice] %><p><%= flash[:notice] %><% flash[:notice]=nil %></p><% end %>
<% if flash[:error] %><p><%= flash[:error] %><% flash[:error] =nil %></p><% end %>
Salil
just curious, why do you always nil the notice and error objects?
Kevin
if you not nil the notice and error then if you render to the the another page same notice/error will appear. I went through the same problem so i keep a habit that always nil the notice/error once i show in the view. Cheer's
Salil
@Salil: that behavior is by design. If you don't want the flash to be passed to the next action, you can use `Flash.now` instead.
JRL
Thank you too Salil. As JRL pointed out, you can just flash.now[:error] and it will automatically be cleared on the next action. That's actually what I'm using for this example.
GoodGets
+1  A: 

I would make this a comment but it doesn't do multi-lined code snippets very well. They're probably "randomly switched" because you're using it like this:

  <% flash.each do |k, v| %>
    <div id='flash_<%= k %>'><%= v %></div>
  <% end %>

In 1.8 hash keys are unordered and because flash is a Hash, you'll get these output in whatever order Ruby feels like at the time. As Ben suggested, putting them in the "correct" order manually would help.

Ryan Bigg
Someone's a mind reader. Yeah, thats pretty damn close to the code I was using in my layout/app file. Thank you too Ryan for the further explanation. (Side note: I'm a fan of your blog.)
GoodGets
Heh not quite a mind reader, just observant of the patterns in Ruby on Rails :). Good to know I've got another fan, too.
Ryan Bigg