Quite often, Ruby on Rails developers use the flash object to store objects for the following request. Flash’s most common use is for displaying messages to users after redirections. Flashes are usually rendered in the application’s layout.

Consider the following 2 scenarios that will stop flashes from working properly

  1. AJAX requests.
    Flash will simply be ignored as it’s rendered in the layout. One way to handle this is to have the AJAX response carry both the normal response + the flash message and have the JavaScript at the client figure out which is which then display the flash message and handle the normal response. This is a bit cumbersome but doable.
  2. Responding with cached pages.
    What if the server responds with a cached page? The layout will never be rendered and so will the flash messages.

So, what we really need is a solution that doesn’t rely on the rendering of the layout or of partial responses.

Have a cookie and be a happy – hopefully not so fat – man🙂
Really, what about storing the flash messages in a cookie? Have JavaScript check that cookie and display the message accordingly?
How do we write the flash message into a cookie? What about an after_filter that writes the flash message into a cookie and then wipes the flash object clean?

So, we need to edit 2 files

  1. ApplicationController
    class ApplicationController < ActionController::Base
      .
      .
      after_filter :set_flash_cookies
      private
     
      def set_flash_cookies
        if(flash[:error])
          cookiesNotification('error', flash[:error])
          flash[:alert] = nil
        elsif(flash[:note])
         cookiesNotification('note', flash[:note])
         flash[:info] = nil
        end
      end

      def cookiesNotification(type, msg)
        begin
          cookies[:notification] = {:type => type, :message => msg.to_s}.to_json
        rescue => e
          #hanlde the exception
        end
      end
    end

    The previous code adds the flash message into a cookie and wipes the flash object clean.

  2. The application layout
    First, we’ll have a function that extracts the message out of the cookie if present and display the message then delete the cookie.

    processNotifications = function(){
      if(Cookies.readCookie("notification")){
        //Cookies is a namespace that has a couple of function that abstracts processing cookies
        eval("notification = " + unescape(Cookies.readCookie("notification").replace(/+/g," ")));
        //show the notification in its normal place
        showNotification(notification.type, notification.message);
        Cookies.eraseCookie("notification");
      }
    }

    We need to make sure that this function is called at proper times i.e. when pages are loaded and after AJAX calls are completed. This can be achieved using the following code which uses prototype javascript library

    //for page loads
    document.observe("dom:loaded", function(){processNotifications();});
    //for AJAX calls
    Ajax.Responders.register({ onComplete: function(){ processNotifications();}});

Who said cookies were bad ?!

Technorati Tags: ,,