views:

33

answers:

2

I show flash messages in my rails app using javascript (essentially every flash message is an overlay div).

The following partial is included in my main layout file and it takes care of displaying the flash. I notice that if I refresh a page, the same flash message keeps reappearing. Anyway to get rid of this? I know I can call a flash.discard though not sure what's the best place to do that and I don't want another controller call just to discard the flash.

<% if !flash.nil? %>
  <% if flash[:notice] %>
  <script type="text/javascript">
      //<![CDATA[
      showFlash("<%= flash[:notice] %>", "flash-notice");
      //]]>
    </script>
  <% end  %>
  <% if flash[:success] %>
  <script type="text/javascript">
      //<![CDATA[
      showFlash("<%= flash[:success] %>", "flash-success");
      //]]>
    </script>

  <% end  %>
  <% if flash[:error] %>
  <script type="text/javascript">
      //<![CDATA[
      showFlash("<%= flash[:error] %>", "flash-error");
      //]]>
    </script>
  <% end  %>
<% end  %>


function showFlash(msg, tp) {
    if ($('#flash_messages_container').length > 0) {
        flashAnimatedHide();
    }

    var flashContainer = $("<div id='flash_messages_container' class='flash-messages " +  tp  + " '></div>");
    flashContainer.prepend("<div id='flash_messages_content'>" + msg + "<span class='go-right sprite close' id='close_flash'></span></div>");
    $('body').prepend(flashContainer);
    flashContainer.animate({
        opacity : .1
    }, '500', function(){
        flashContainer.css('opacity', 1)
    })
    $('body').css('margin-top', flashContainer.outerHeight());
    $('#close_flash').click(function() {
        flashAnimatedHide();
        $('body').css('margin-top', '0');
    });
}

UPDATE

I suspect this is happening since I starting using etags for cient side and reverse proxy caching. So I guess the refresh is simply loading the cached page, which contains the flash messages in the flash container. So how do people discard flash when caching is enabled?

+1  A: 

I encountered duplicated flashes messages too before, seems the result is simliar but not sure if the same case.

Are you using flash[:notice] = "something while the action render :action => "somepage"?

ie.

def some_action
  flash[:notice] = "some notice"
  render :action => "other_action"
end

Then you will find the flash[:notice] duplicated after refresh.

The solution is to use flash.now instead:

def some_action
  flash.now[:notice] = "some notice"
  render :action => "other_action"
end

and nothing else needed to be changed.

Please tell me if this cannot solve your problem.

PeterWong
I am doing a flash.now[:notice] = "signed out" redirect_to_back_or_default root_path. Odd enough with this, I don't even see the initial flash message. I think my problem is related to caching, the 2nd refresh that repeats the flash is being served straight from the browser cache (it's a 304 not modified response) and the cached version of teh page in the browser contains the original flash message. Not sure how to clear it.
badnaam
`flash.now` is for `render` while `flash` is for `redirect`. If you use `flash.now` with `redirect` (in your case), the flash messages will be lost. If you use `flash` with `render`, flash messages with be duplicated after you refresh or go to other page. It probably the working principles of flash instead of the caching.
PeterWong
BTW, down-voter could you mind explaining why the down vote?
PeterWong
thanks for your help, but the answer does not address the problem. I don't know why this was being upvoted. This has nothing to do with flash, the problem is caching.
badnaam
So if the this due to the etag, why don't you calculate the etag by both the object itself with the flash (no flash, success flash or error flash, etc). Then if in the new request, no flash is generated, then the etag would change.
PeterWong
A: 

Well here is the solution I used, let me know if there is anything better out there. This relies on cookies being enabled, is that something worth worrying about?

<% if !flash.nil? %>
  <% if flash[:notice] %>
    <% cookies[:flash_notice] = flash[:notice] %>
  <% end  %>
  <% if flash[:success] %>
    <% cookies[:flash_success] = flash[:success] %>

  <% end  %>
  <% if flash[:error] %>
    <% cookies[:flash_error] = flash[:error] %>
  <% end  %>
<% end  %>

and then use javascript to show the flash message and remove the cookie

function doFlash() {
    if ($.cookie("flash_success") != null) {
        showFlash(removeSpace($.cookie("flash_success")), "flash-success");
        $.cookie("flash_success", null);
    }
    if ($.cookie("flash_notice") != null) {
        showFlash(removeSpace($.cookie("flash_notice")), "flash-notice");
        $.cookie("flash_notice", null);
    }
    if ($.cookie("flash_error") != null) {
        showFlash(removeSpace($.cookie("flash_error")), "flash-error");
        $.cookie("flash_error", null);
    }
}
badnaam