I am doing some exception handling in my controller, when there is an exception thrown in :create action, I will render to the :new action and show a flash message.
Everything works fine, I can see the flash message when exception caught, but when I redirect to(handly click) other page, the flash message still here. Then I redirect to another page(the second handly click), the message could disappear.
Anyone who knows what is the reason?
My controller code:
class MessagesController < ApplicationController
rescue_from Exception, :with => :render_new
def new
end
def create
end
private
def render_new
flash[:alert] = t("uploading_error")
render :action => :new
end
end
My layout code (Haml):
%body
#content
- unless flash[:alert].blank?
#alert= flash[:alert]
Replace
flash[:alert] = t("uploading_error")
with
flash.now.alert = t("uploading_error")
and see if that is the result you expect?
flash[:alert]
will stay around for the next page (hence it only disappears at the second redirect); but flash.now.alert
will only display for the current page.
Deciding between flash.now and regular flash is a pain in the ass and quite fragile in my experience. I use regular flash and then modify my partial which displays the flashes to delete the contents of each flash after the user has seen it. I think this is better because
a) you don't have to think about it
b) "has the user seen it?" (ie "has the flashes partial been rendered out?") is the best criterion for deciding whether or not to clear the flash, rather than any logic in your app.
My flash partial looks like this - i also use a bit of jquery just to highlight the flashes (ie make them flash yellow for a second):
<div id="flashes">
<% if flash[:notice] %>
<p id="flash_notice" class="messages notice"><%= flash[:notice] %></p>
<%= javascript_tag "$('#flash_notice').effect('highlight',{},1000);" %>
<% end %>
<% if flash[:error] || flash[:errors] %>
<p id="flash_errors" class="messages errors"><%= flash[:error] || flash[:errors] %></p>
<%= javascript_tag "$('#flash_errors').effect('highlight',{},1000);" %>
<% end %>
<% flash[:error] = flash[:errors] = flash[:notice] = nil %>
</div>
An alternative is to use flash.clear at the end of the partial like so:
<% if !flash.empty? %>
<div class="flash-messages-container">
<% flash.each do |name, msg| %>
<% if msg.is_a?(String) && [:success, :info, :error, :warning].include?(name) %>
<div class="flash-message" data-type="<%= name %>" >
<%= msg %>
</div>
<% end %>
<% end %>
</div>
<% flash.clear %>
<% end %>
I also suggest to clear the flash
inner hashes upon displaying.
flash.clear
will do the trick in a clean way :
<% flash.each do |key, value| %>
<div class="alert alert-<%= key %>">
<%= value %>
</div>
<% end %>
<% flash.clear %> #this line clears the object
http://api.rubyonrails.org/classes/ActionDispatch/Flash/FlashHash.html#method-i-clear
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With