Sunday, October 16, 2011

Rails Flash for Presentation Logic: Good Idea or Cause for Trouble?

Rails comes with a feature called Flash that simplifies displaying messages to users after redirecting them to another page on the site. Such messages can include confirmations, greetings, congratulations, etc..

For example, upon a user submitting a help request on the site, they see a flash message on the next page confirming that the request has been submitted and is being reviewed.

The HelpRequestsController create action code would contain logic like the following:

if help_request.save
  flash[:notice] = 'Your help request has been submitted and is being reviewed.'
  redirect_to root_path
else
  flash[:error] = 'The help request is missing required information.'
  render :action => 'new'
end

This would display a view element as follows, typically at the top of the page:




The key benefit to using the flash hash is that its data persists whether the controller action renders a page in the same request, or redirects to another page initializing a new request. It relies on the session store behind the scenes to persist data and clear the flash after the next request, saving the developer from performing that work themselves.

Now, this blog post is not about use of the flash hash for displaying messages. It is about whether it is a good idea to rely on the flash ability to keep data for one more request to store data that will affect presentation logic.

I recently saw an example of using the flash to store variables that get rendered in hidden fields and later used by JavaScript logic on the page for determining whether to display certain pieces of data or not.

The logic unfortunately broke the moment someone Ajaxified the JavaScript logic as it ended up hitting another controller action that was not redirected to from the original action that requested the page, thus losing the flash data in the process.

To illustrate:

Originally:

Action 1 sets flash and redirects to Action 2
Action 2 uses flash in rendering elements

After Ajaxification:

Action 1 sets flash and redirects to Action 2
Action 2 renders a page that performs an Ajax request in its JavaScript
Action 3 attempts to use flash in rendering elements but does not find data

One way to fix the problem that a developer attempted was to use the flash.keep method in the last redirected action to keep the flash data for one more request. Unfortunately, that approach is fickle because if multiple Ajax requests hit the server, the flash data will get lost eventually unless all their actions perform a flash.keep. Also, if the code ends up performing flash.keep everywhere, that defeats the purpose of using flash over the session.

My understanding is the flash hash was created to flash a message to the user once after a certain request. So, I personally limit its use only to that use case to keep any code around it easily understandable and maintainable by other developers. If I needed to persist presentation logic data across requests, I usually rely on the session instead.

What is your opinion on the matter?

No comments: