This article is written by Tomomichi Onishi, and was published in the 'Best of' issue of the Software Developer's Journal. You can find more articles at the SDJ website.
Overview
In this tutorial, we'll see how to create a web application using Sinatra, the light-weight Ruby framework, and how to deploy it on Heroku, the web application hosting service.
We create a simple web application as a sample, using Hyakunin-Issyu, the beautiful anthology of Japanese ancient poems, as a theme.
This app has only two pages; the one shows the list of all the poems and the other one shows the detail of each poem.
(Don't worry if you never heard of Hyakunin-Issyu. You'll see a quick guide at the end of this introduction.)
What you will learn...
Through this tutorial, you'll learn the following.
- how to use Sinatra framework
- how to deploy your app on Heroku
- general understanding of Hyakunin-Issyu
What you should know...
This tutorial expects you to know.
- Ruby
- Gem management using Bundler
- Git
- Haml
About Hyakunin-Issyu
Hyakunin-Issyu, or the one hundred poems by one hundred poets, is an anthology of one hundred tanka, a Japanese poem of thirty‐one syllables, selected by a famous poet in the medieval period.
http://en.wikipedia.org/wiki/Ogura_Hyakunin_Isshu – Wiki page of Hyakunin Isshu
Tanka is made of thirty-one syllables, five-seven-five for the first half of the poem and the seven-seven for the last half.
As it can't contain very much information on such a limited number of words, it's very important to feel the aftertaste of the poem.
Composing a poem with very selected words, describing the delicate feelings and the beautiful scenery of nature, is a very Zen-like way and this is the culture we Japanese should be proud of.
We often play the Hyakunin-Issyu based card game called "Karuta" in the New Year's holidays in Japan.
The basic idea of the Karuta game is to be able to quickly determine which card out of an array of cards is required and then to grab the card before it is grabbed by an opponent.
Chihayafuru, the karuta themed comic, became a big hit in Japan and now this traditional culture has became popular again.
Please take a look at this comic if you are interested.
http://www.youtube.com/watch?v=rxebYxY9NXE – opening video for Chihayafuru anime
Okay, I think that's enough for the intro.
Now it's time to start the tutorial.
Using Sinatra
The first half of this tutorial is to create an simple application with Sinatra.
The very basics of Sinatra
Minimum construction
To start with the smallest possible project, all you need is two files.
Listing 1. The construction of the project files
|-sample
|-main.rb
|-Gemfile
The core parts of the application will be written in main.rb.
At the moment, we only need to add routing for root ('/'). So any requests for '/' will be processed here.
In this example, we'll output a simple "hello world".
Listing 2. The minimum implementation of main.rb
#main.rb
require "sinatra"
get '/' do
"hello world."
end
Next, make a Gemfile for gem management. Now you only need a Sinatra gem.
Listing 3. List gems on Gemfile
#Gemfile
source :rubygems
ruby '2.0.0'
gem 'sinatra'
From the terminal, run "bundle install" to install gems to the project.
The project settings are almost done!
Move to the project root and run "ruby main.rb" from the Terminal.
The application will be run on port:4567 (this may be different on your machine, so be sure to check the output in Terminal).
Open your browser and access 'localhost:4567'.
If successful, you should see the words "hello world" displayed there.
Adding more pages
Okay, now we're going to add some more pages to this app (it's just too simple, otherwise!).
Edit main.rb to do this:
Listing 4. Adding more page to main.rb
#main.rb
...
get '/poem' do
"this is another page!"
end
Well done! Now we have another page with the route '/poem'.
Restart the project by running "ruby main.rb" and access "localhost:4567/poem" in your browser.
You should now see "this is another page!" displayed there.
Auto reloading Sinatra
It can get tiresome to restart the process every time you've changed something in the code.
To make things easier, let's introduce auto-reloading into our app.
Listing 5. Add sinatra-contrib to Gemfile
#Gemfile
...
gem 'sinatra-contrib'
Add this line to Gemfile and run "bundle install" again.
Then require sinatra/reloader on main.rb.
Listing 6. Require sinatra/reloader in main.rb
#main.rb
require 'sinatra'
require 'sinatra/reloader'
...
That's all we need. Try restarting main.rb again (it's the last time, I promise!), then access "localhost:4567" in the browser.
Next, change the "hello world" message on main.rb and refresh the page. If all goes well, you'll now see the message changed without having to restart.
Accept parameters
One last thing for this section is to accept URL's with parameters, like "/poem/13", so that the page contents update based on this new value.
Listing 7. Accept parameters in main.rb
#main.rb
get '/poem/:id' do
"this page shows the detail of poem-#{params[:id]}"
end
Add :id to the get part, and use that param with params[:id].
Now try accessing "localhost:4567/poem/13". The content should have changed.
Developing the main parts
Okay, we now have much of the core of the project completed.
I have made a HyakuninIssyu gem which allows us to use poem data easily, so lets install it.
(don't worry, the file contains English data, also)
If you want to know how to use the gem, please check it out, here.
https://github.com/Tomomichi/HyakuninIssyu - Tomomichi/HyakuninIssyu
Install HyakuninIssyu gem
Add the gem to Gemfile and run "bundle install" again.
Listing 8. Add HyakuninIssyu gem to Gemfile
#Gemfile
gem ...
gem 'HyakuninIssyu'
You'll also need to 'require' it in main.rb.
Listing 9. Require HyakuninIssyu gem in main.rb
#main.rb
require ...
require 'HyakuninIssyu'
With that done, check to make sure it works.
Listing 10. Add sample code to test gem
#main.rb
get '/' do
data = HyakuninIssyu.new
data.poem(1).kanji
end
Add this to main.rb and then access "localhost:4567" in your browser.
Have you found the poem of Emperor Tenchi (in Japanese this time)?
This poem describes a miserable life of farmers, but isn't it strange that the emperor composed a poem like this? How could he understand the feelings of those people?
It's one of the mysteries of Hyakunin-Issyu.
Index page
Okay, we'll now finish the index page using this gem.
This page shows the list of all the poems. Use the poems method of the gem:
Listing 11. List all the poems in index page
#main.rb
get '/' do
data = HyakuninIssyu.new
@poems = data.poems
end
That's it. We set all the poems data to @poem.
Now it's time to finish view files.
Use separate view files
It'll be messy if you write all the html document in main.rb, so we will divide the code and use separate view files.
Listing 12. The construction of the project after adding view files
|-sample
|-...
|-views
|-index.haml
|-poem.haml
Add a views directory and create haml files there.
Install haml gem to use haml files.
Listing 13. Adding haml gem to Gemfile
#Gemfile
...
gem 'haml'
And now create the index.haml file to show the list of poems.
Listing 14. Index.haml
#views/index.haml
%h1 INDEX
- @poems.each do |poem|
- unless poem.nil?
%p #{poem.kanji}
%small #{poem.en}
One last thing to do is to declare the use of haml file in main.rb.
Listing 15. Declare the use of haml file
#main.rb
get '/' do
...
haml :index
end
This simply means that it uses views/index.haml as a view file.
Now let's access "localhost:4567" again to see whether the content of index.haml is shown there.
Remember that we used @poems in main.rb.
This enables us to pass that variable to the view file.
Now the index page is done. Let's move on to the second page.
Poem detail page
As we enabled the parameter handling already, we use it to get poem data from the gem.
Listing 16. Developing poem detail page
#main.rb
...
get '/poem/:id' do
id = params[:id].to_i #treat the parameter as an integer
data = HyakuninIssyu.new
@poem = data.poem(id)
@poet = data.poet(id)
haml :poem
end
We set the poem data to @poem and @poet, and declared that we use views/poem.haml as a view file.
The poem.haml file should look like this:
Listing 17. The content of poem.haml
#views/poem.haml
%h1 POEM
%div
%h2 Poem Info
%p #{@poem.kanji}
%small #{@poem.en}
%div
%h2 Poet Info
%p #{@poet.name.ja}
%small #{@poet.name.en}
Access "localhost:4567/poem/13" in the browser, perhaps with a different poem number, and check the poem data is shown correctly.
Finish the development
To finish the development of this app, we'll link these two pages.
Listing 18. Add a link to index.haml
#views/index.haml
%h1 INDEX
- @poems.each do |poem|
%p
%a(href="/poem/#{poem.id}") #{poem.kanji}
%small #{poem.en}
And add a very simple back link to poem.haml.
Listing 19. Add a link to poem.haml
#views/poem.haml
...
%a(href="/") Back
Okay, we've now finished developing this very simple Sinatra web application.
It shows the list of all the poems of HyakuninIssyu, and you can see the detail of each poem.
Now let's try to deploy this to Heroku.
Heroku Deployment
The last half of this tutorial is deploying the Sinatra application to Heroku.
Before continuing, please sign up and create your account on Heroku.
https://id.heroku.com/signup – Heroku Sign Up
Also you'll need the Heroku Toolbelt to use the heroku command.
Please download this from the link below:
https://toolbelt.heroku.com/ - Heroku Toolbelt
Okay, now let's get started.
Create a Heroku app
First you need to create a Heroku app.
Move to a new project root and run the following comand:
Listing 20. Create a new heroku app
heroku create YOUR-APP-NAME
That's all. The empty app is created on heroku and it's added to your git remote repository.
(You can check this by running the "git remote" command)
Create a system startup file
Before deploying your app, you need the system startup file to run your app on Heroku.
Create config.ru file as shown below:
Listing 21. Create a config.ru file
#config.ru
require 'bundler'
Bundler.require
require './main' #requiring main.rb
run Sinatra::Application
Introduce a git version management
As we use the git command to deploy the app to Heroku,
we need to introduce git and commit the changes so far.
Listing 22. Introduce git version management
git init
git commit -m "initial commit"
If you're not familiar with git, check the Git Book or other tutorials.
http://git-scm.com/book – Git Book
Now we're ready for deployment!
Deploy to Heroku
Deploying to Heroku is extremely easy. Just run the following command:
Listing 23. Deploy command to Heroku
git push heroku master
That's it. After successfully building your app on Heroku, run "heroku open" or
access "APP-NAME.heroku-app.com" to see your app.
Is your app working well? If you find some errors, please run "heroku logs" to see what's wrong.
Okay, that's the end of the tutorial.
The final version of the codes are in my GitHub repository.
If your code doesn't work, please check there and compare it with yours.
And more...
This tutorial covers only the very basics of Sinatra and Heroku to keep it simple.
If you find them interesting, please go further to get to know them better.
The following topics would be your next challenges:
Sinatra
- use layout/shared files in view
- use Helper
- introduce SCSS, CoffeeScript
- internationalization of the app
- test with Rspec
- introduce login management with Sorcery
Heroku
- prevent Heroku app from sleeping with Heroku Scheduler
- monitor the app performance with NewRelic
- use thin server instead of webrick
- build the staging app
- connect to the database and backup it
- use Travis CI for the automatic test and continuous deployment
Hyakunin-Issyu
- learn the poems of Hyakunin-Issyu and remember them
- read Chihayafuru to know the poems more.
- join the Karuta game.
If you have an interest on these topics, I'll write the next article about them.
Please send me a request to let me know what you would like next: tomomichi.onishi@gmail.com.
Some explanation from SDJournal
Last time we confused our CodeProject Readers badly so we want to apologize and explain ourselves as well. We edited the previous articles we posted at CodeProject website to fill the informations about authors. Then those articles goes to the main site as "New" posted articles. The truth is - they were here published years ago.
That was not we want to happend and many of you asked us why we post old texts. We don't but in fact we edited them so they appear like a new ones. We're deeply sorry. In the future we will be more careful. If you want write us your review about this article (which was published in our 'Best of' issue here: http://sdjournal.org/best-of-python-game-development-joomla-selenium/) we will be very grateful. Also if you like our work, we may have special subscription offer for you here: http://sdjournal.org/subscription-with-trial/. We hope you enjoyed your lecture.