On my Flight Historian application, a number of my pages make use of the
flash.now session messages capability for errors, warnings, successes, and informational messages. However, some of those pages needed to have multiple messages of the same type (e.g., multiple warnings), which flash didn’t allow me to do. Additionally, I had some views that were generating status messages of their own (for example, if a collection was empty on a page that had multiple collections), and so I ended up with several ways to generate messages that didn’t output consistent HTML.
To fix this, I wrote my own messages structure.
I first created a
message partial which would render an individual message banner:
This partial accepts a message
type (error, warning, etc.) which is used to select the CSS class, and the message
In order to shorten the partial call, I wrote a
render_message(type, text) method in the application helper to call the partial:
If necessary, I can call this directly from the view to insert a message anywhere I want. However, I also need to be able to have controllers add messages to be displayed at the top of the page.
I created an
add_message(type, text) method in the application controller which creates an array of message hashes (if one doesn’t already exist) and allows me to add messages to it.
Now, I need to display all messages. Back in the application helper:
Since my messages can have different priorities, when I display a page with multiple messages, I want them sorted with the highest priorities first. My
order array defines the order I want my types sorted in.
Next, I make sure a
@messages array exists, and then I merge any
flash messages into my messages array, so they display the same as any other message. For each flash, the hash’s key is used as the type.
Then, I get the index of each message type in my
order array, and sort on that. If a message has a type that’s not in the array, it’s given an order number of the length of the array. Since that number will always be higher than any array index, the unknown message types will be sorted below the defined message types.
Finally, I loop through the messages with
render_message to render the message partial for each, and then join all the partials together. Since this is the last operation of the method, this string of joined message partials will be returned by
Finally, I call
render_message at the top of the page in my application layout:
The end result works well. Here, I’m explicitly mixing a status message from my controller (yellow) with a flash message from a database update (green):
And that’s it! I wish the
flash itself supported having multiple messages of the same type, but since it doesn’t, this works well for me.