The flash is a handy little helper method in Rails that lets you store information between requests. When your application processes a request, it usually ends by redirecting to another url, which generates another request. The flash is a hash-like object that stores temporary values such as error messages so they can be retrived later – usually on the next request. It also removes the information once it has been used.
Sinatra Flash is a neat little extension written by Stephen Eley. It includes all of the functionality of the Rails Flash, but, in keeping with Sinatra’s minimalist nature, it uses much less code.
First of all we need to install the sinatra-flash gem, like so:
gem install sinatra-flash
To try out the basic functionality, we’re going to need a basic Sinatra app. Create a file called ‘main.rb’ that contains the following code:
These are the gems needed for our basic application – obviously Sinatra, and I am using the Slim rendering engine (feel free to use another such as erb or haml if you prefer). In order to use Sinatra Flash, we need to require the gem. Sinatra Flash uses sessions to store the data from one request to another. Sessions are disabled by default in Sinatra, but it’s simple to use them, just add the following line after the requires:
Next we will create a simple handler for our index page:
Nothing major is happening here, it will just display the index view when the user goes to the root url. We’ll need a layout and some basic views to get us started. I’m going to use Sinatra’s awesome inline views so that I can keep everything in the same file. Just put the
__END__ declaration at the bottom of your file and write the view code afterwards. Here is a very basic HTML5 layout and view that just displays a heading.
Let’s test this out. Open up a command-line prompt and navigate to the folder that contains the main.rb file, then type the following:
$> ruby main.rb
Now go to ‘http://localhost:4567’ in your browser and you should see the following:
Now let’s have a go at using the Flash. The usual reason that you would want to use this functionality is when somebody interacts with your site by pressing a button or visiting an url. Your app will go off to the relevant url, process some information and then redirect the user to another url. The flash allows you to give some feedback from when the information was processed that would otherwise have been lost. To demonstrate this, let’s add a button to the index page. Change the
@@index view code to the following:
This just adds a button that will send a post request to the server. We need to add a handler to deal with this request, so add the following code after the root handler:
This sets an instance variable called
@time and then redirects us back to the index page. Let’s try to access the
@time variable on the index page. Add the following to the
Now, restart the server (press ‘Ctrl’ and ‘C’ together and then retype
ruby main.rb in the command line) and have a look at the page. Try pressing the ‘What Time Is It?’ button and you should see the following:
That’s right, the time isn’t showing. This is because the value of
@time was lost once we redirected to the index page. We need to use the flash to pass it on to the next request. Change the post handler to the following:
And change the index view to the following:
Now restart the server, reload the page and try pressing the ‘What Time Is It?’ button. If everything is working correctly, you should see the time displayed:
The previous example showed how to set and display the flash, using the syntax
:time is a key that can be anything you like. The
flash[:key] helper method is used in handlers to set the flash and then used in views to retrieve it. You can use different keys to correspond to different messages, as we’ll see in the next section.
The Flash Farm Shop
Now we’ve seen the flash in action, I’m going to build a simple e-shop style site that shows off the most common use-cases of the flash. I’ve created some animal pictures to show off the livestock of our store that you can see below:
***pictures of the animals
To begin, let’s change the index view so that it shows off some products to sell:
Note that you will need to save the pictures of the animals in a folder called ‘public’ in the same directory as the
Each animal has an ‘Add to Basket’ button underneath it’s button, so let’s add a handler to do this when the button is pressed. Add the following code after the other handlers:
This uses the paramater
:animal in the url that Sinatra makes available in the
params hash. This can be used to create a generalised url for adding an animal to the shopping basket. We’re not actually going to implement any e-store functionality in this tutorial, just mimic it, so the comment at the start of the handler just shows that this is where your logic for implementing the next big thing in e-commerce would go. Then we store a message in the flash to say that the process was carried out successfully. If you try testing this out at the moment, nothing will appear because we haven’t placed the message in the view. We’re going to put the message in the layout so that it appears at the top of the main page and also so it will show on all pages. Change the layout view to the following:
This should work – when you click on the ‘Add to Basket’ button under each animal, a message should appear at the top of the page.
You might notice that there is also a link to a stylesheet in the layout. This is because now our flash functionality is working, it’s time to give it a bit of style. One of the things I love about trying things out in Sinatra is how you can add new functionality really easily in the same file. To add styles using Sass all we need to do is add a new view at the bottom of
main.rb. Here are a few styles to get started:
Now all we need is to place the following handler to make sure that scss is used to pre-process those styles:
Now restart the server and page and you should see a much nicer looking shop front!
As we saw before, you can use different keys in the flash for different purposes. Let’s say that we also want to provide some additional information when a duck is ordered. Let’s modify the handler to add this extra information to the flash:
To make sure any flash messages with the key of
:info are shown, we need to add a couple of extra lines to the layout:
Adding all these lines of code for every different type of of flash message has the potential to get very annoying and isn’t very DRY. Another problem might be that you don’t know which flash keys will be used when the layout is created. This is easily solved by the very handy
styled_flash helper method. This goes in any of your views and iterates over the whole flash, displaying all of the messages inside their own div element that has the same class as the flash key. All we need to do is change our layout to the following:
This will create the following markup:
We now have some styling hooks that allow us to style each type of message a bit differently. Below are a few styles that I’ve nicked from the Twitter Bootstrap notifications:
Restart the server and test this out and you should see a nicely styled page that looks just like how the pros do it:
Now that we have lots of different styles, it’s time to test them all out. To do this I am going to implement a mock checkout function. The button is already there in the layout, so all we need is a handler to deal with it:
I’ve contrived an example here that allows us to give different messages to the users. To start with Flash Farm’s payment processing is not up to scratch and there is a 1 in 3 chance that something goes wrong, so an error message is displayed in the flash. To make up for this there is a 1 in 3 chance that a discount will be applied. This involves redirecting to the ‘/discount’ page, so let’s add a handler for this:
You’ll also notice that when the checkout process has finished, you get redirected to the ‘/finish’ page, so that will also need a handler:
I’m reusing the
@@index view here, so it will look just the same as the root url, but in the future it might show other products that the shopper may be interested in. For now, let’s just display a nice thank you message for our loyal shoppers.
If you have a go and testing this out, you should notice there are a few problems. Nothing is actually wrong – the flash is just working the way we described earlier. First of all, if a discount is applied, then the message about the discount is displayed, but the message that the payment was successful is not. This is because the flash discards all messages after one request, so the success message was removed when it was redirected to the discount page. There is a simple way to get round this using the handy
This just keeps all the messages that are stored in the flash for one more request, so now both messages will be shown if a discount is applied.
The other problem is that the message that says thank you for shopping at Flash farm is not shown when we visit the ‘/finish’ page. Again, nothing is wrong here, it’s just that the flash is supposed to be shown on the next request, not the current request. Try reloading the page and the message will then be displayed. As you might have guessed there’s also a method to get round this,
This displays the flash message straight away on the current request. This is particularly useful if you use Ajax to process any requests in the background, as a redirect is not used, so you need to show the message on the current request.
That’s All Folks
That’s about all there is to the sinatra-flash gem. It’s a neat little piece of code that does its job brilliantly, I hope you find it useful. It is also a great example of how to make a Sinatra Extension. If you look at the code on Git Hub, you’ll see that there’s less than 50 lines of code. Stop by and have a read – you’ll pick up some good pointers about how Sinatra’s extensions work. I’ve uploaded the finished Flash Farm site on Heroku and put the code on Git Hub. Feel free to ask any questions in the comments below.