Recently I started experimenting with the Roda framework to build web applications but as there are not many tutorials, or blog posts in general, about Roda, I thought I'd share my experiences here. Over the coming weeks I'll be writing a number of articles on using Roda but rather than having to duplicate lots of setup code I think it'll be easier to have a base app to work from. So, in the next two articles I'll be building an extremely simple blog using Roda, Postgres, and the Sequel ORM. For this first part we'll deliver static content, leaving User accounts and posts for part two.
For those who want to follow along, my system is Mac OSX 10.9, along with the following software versions;
Your application may not work if you use a different version of Roda than what I specify here, but for the rest, you shouldn't encounter any issues if your versions are a little older/newer.
Installation of Ruby and Postgres is left as an exercise for the reader.
This is actually the simplest part of the whole procedure as Roda is just a regular GEM. We are however going to be using Bundler for our gem management so first you'll want to install that, followed by Roda;
$ gem install bundler $ gem install roda
Unfortunately there are currently no site generators in Roda like there is in Ruby on Rails (
rails new myapp). This means we'll have to generate our application directory and file structure by hand. Here's the outline that we'll be using for our simple blog;
- myapp/ - models/ - public/ - views/ - config.ru - Gemfile - myapp.rb - models.rb
Go ahead, create the base app directory;
$ mkdir ~/myapp $ cd ~/myapp
I always like to use Bundler for the gem management so we'll need to create a Gemfile in which we'll specify the basic gems requirements for delivering static content;
# ./Gemfile source "https://rubygems.org" gem "roda", "~> 2.1.0" gem "tilt", "~> 2.0.1" gem "erubis", "~> 2.7.0"
Remember to run
bundle install now, and each time you make a change to this file.
At present we have just three dependencies; the first is Roda itself, but we're also including
erubis so that we can use ERB templates in all our views.
Like all Ruby web frameworks, Roda is built on top of Rack, so we're going to need a
config.ru so that when we start the server (with rackup), our application will be loaded;
# ./config.ru require File.expand_path("../myapp", __FILE__) run Myapp.app
The final part of our setup procedure is to create the main application class and inherit from Roda;
# ./myapp.rb require "roda" class Myapp < Roda route do |r| r.root do "Hello!" end end end
Inside our class we use Roda's
route, which is where we define all the routing for our website. For the moment I've just set
root to show a simple welcome message. Let's boot up our application to make sure everything is working as expected;
Check the output of that command to make sure you use the correct port when viewing the site in your web browser. Mine says,
WEBrick::HTTPServer#start: pid=46685 port=9292. Open your web browser and type in the url;
localhost:9292. If all is well you should see the message: Hello!
Now that everything is setup and working, it's time to start fleshing out the application. Like the good developer we are, we're going to want to make use of templates so as to make sure we're using standard styling across all pages. We'll create a
layout template using Ruby's built in ERB, along with using Twitter's Bootstrap framework so we get all their styling goodness for free.
All "views" will be placed in a
views directory, while additional CSS/JS and images should go in a directory labelled
$ mkdir ~/myapp/public $ mkdir ~/myapp/public/css $ mkdir ~/myapp/public/images $ mkdir ~/myapp/public/js $ mkdir ~/myapp/views
All menu items, stylesheet references, page headers/footers and sidebars, will all go a
layout.erb. As we'll be using Bootstrap I'm going to copy their example layout pretty much as-is. Copy the follow into a new file named
layout.erb, and place it in the
# ./views/layout.erb <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>My Roda Website</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css"> <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> <![endif]--> </head> <body> <div class="container"> <div class="page-header">My Roda App</div> <%= yield %> </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script> </body> </html>
yield in that code? That is where our individual page content with be inserted. For now we'll just add some stand-in text;
# ./views/homepage.erb <p>Welcome to my new website!</p>
Note the use of the
.erb extension. Any view file that uses the .erb extension informs Roda to use tilt/erubis when processing.
Roda needs to be told to use our views, images, css, and js files, which can be done via two plugins;
static. These will be added to the main application class as follows, and while we're there, we'll also tell Roda to use that
homepage.erb view we created when the web browser points to the homepage url.
# ./myapp.rb class Myapp < Roda plugin :static, ["/images", "/css", "/js"] plugin :render plugin :head route do |r| r.root do view("homepage") end end end
You may also notice that I've added the
:head plugin. If we don't then any client that just checks headers will see a 404 response, which could have a negative impact with Search Engine bots.
That's it! Restart your server (CTRL-C then run
rackup again). If all is well then you should be seeing the sites' banner message (My Roda Website) from the layout file, along with the welcome message we placed in the homepage view.
Our final task for this part of the tutorial is to create a couple of new web pages. Pretty much any site you visit will have both an about page and contact page. All our previous work makes this bit of the tutorial a breeze. Let's start by creating some new views for these pages;
# ./views/about.erb <h1>About Me</h1> <p>I am currently building my first Roda application!</p>
and the contacts page;
# ./views/contact.erb <h1>Contact</h1> <p>You can send me an email or connect with me on Twitter/Facebook/Google/etc.</p>
These pages won't be accessible until we have some routes for them. Open up the main app class and add the following;
# ./myapp.rb route do |r| # ... r.get "about" do view("about") end r.get "contact" do view("contact") end end
Pretty simple huh? We have two GET verbs, each with a call to their respective view templates. When you visit
localhost:9292/about Roda will call up the
about.erb template, which is then rendered inside of
To aid our visitors in accessing these pages we're going to add a navigation bar to the top of the site layout. Directly after the opening body tag add this Bootstrap navbar markup;
# ./views/layout.erb <body> <nav class="navbar navbar-default navbar-inverse"> <div class="container"> <ul class="nav navbar-nav"> <li><a href="/">Home</a></li> <li><a href="/about">About</a></li> <li><a href="/contact">Contact</a></li> </ul> </div> </nav> # ... </body>
Restart the server and start exploring your new site.
In under 100 lines of code we have a fully functioning website. Sure, there's a lot more that can, and probably needs to be done, but you can go a long way just with this simple code.
Be sure to check out the Roda pages to learn more about this routing tree framework. You'll also find lots of additional plugins which certainly take the pain out of web development.
1:44am, Jan 17
Line 10 and 14 are missing from the second myapp.rb code source.
# ./myapp.rb require "roda" class Myapp < Roda plugin :static, ["/images", "/css", "/js"] plugin :render plugin :head route do |r| r.root do view("homepage") end end end
7:01pm, Jan 17
Many thanks for the fix, I've updated the post.
Comments have been turned off.
Hi, my name is Michael and this is my personal blog. Here I'll be posting various coding thoughts and experiments; everything from writing blogs in Ruby, to Go tools and Z80 Assembly. This site is powered by Thunderaxe, a blogging platform built using the Go language.