Lately I have heard quite a few people mention the Sinatra framework, which is a very light-weight webframework for Ruby. Already being fond of Ruby I decided to take a look at Sinatra, so I could see what all the fuss was about.
Right off the bat I decided to install Ruby instead of going with IronRuby like I had done so far. Sadly I am not feeling too secure about the future of IronRuby, since Microsoft stopped investing in it - but of course I really hope that it will continue to go foreward as open source. Because of this insecurity and because of basic curiosity I decided to to “pure Ruby”. After all getting started is just running the installer you can download from ruby-lang.
You guessed it: “Hello world!”
I see no reason to chance a concept that works, so the first thing to do was a basic Hello world application. If the idea is “light-weight”, this should be done in no time – which it turnes out it was.
First we need to install the sinatra gem. A gem is similar to a NuGet package – with the idea for NuGet originating from Rubys gems. To run it simply open the ruby console and run the following command:
gem install sinatra
Next up is the actual code that we want to run, so simply create a new folder, and added a hello.rb file with the following code in it.
require 'rubygems'
require 'sinatra'
get '/' do
"Hello world!"
end
What this does is add a get handler for the root of the site, that returnes “Hello world”. Just like we use get it is possible to write post, put and delete to handle the different http verbs – thus giving you what you need to do REST. So now the app is ready to run by going navigating to the folder in the console and typing ruby hello.rb. This will start WebRick, which is a webserver that will serve our application, listening on port 4567. So to verify go to http://localhost:4567
If you look in the console you will see that WebRick is not too happy that it can’t find a favicon, so to get rid of this warning you can add a favicon.ico to a ./public folder.
Bread and butter – layman’s terms for params and helpers
Probably the first things that you will need to build anything interesting is the ability to use paramters in your routes, and helpers to provide some basic functionality. Adding a route with a parameter is simply done by extending the string argument passed to the get method with the route using :myParam placeholders like {myParam} is used in ASP.NET MVC.
Writing a helper is done by passing a codeblock to the helpers method with the functions you wish to add. So putting this together we can do:
helpers do
def yell(source)
source.upcase!
end
end
get '/hi/:name' do
"Hello #{yell(params[:name])}"
end
Running the app again from the console should now let you visit http://localhost:4567/hi/Johnny
So now we actually have what we need to build something that can take input, do some structured logic and output “something”.
Templates galore
With code in place to handle requests, we need some feasible way of generating output, and now we actually have quite a few ways to go. Being light-weight and modular Sinatra allows you to choose from a wide range of templating engines. Haml, Erb, Scss, Less, Markdown and a bunch of other view engines can be use simply by installing a gem.
For most websites what we will need is viewengines that can help us do html and css so I chose to take a look at Haml and Less. I have heard nice things about haml, and I have used dotLess which is the .NET version of Less a few times before – so it was the choises that made most sense to me personally.
Haml
Haml is a templating language that allows you to write html in a really compact fashion, by using significant whitespaces, conventions and concise syntax. There are also implementations of Haml for a number of MVC webframeworks, so it is pretty widely adopted.
To get started using haml run the gem with “gem install haml” and require haml in your code. When this is done you simply write haml :index to render a index.haml file that you create in ./views/index.haml.
require 'haml'
get '/hi/:name' do
@name = yell(params[:name])
haml :index
end
Shortly put haml uses indentation to define scope for tags, which are themselves defined with a percentage sign. Attributes are declared as a hash after the tag-declaration, or css like syntax can be used with the convention that an omitted element name means a <div> is assumbed. I know this seems confusing to most but I thing the sample says it all – if you think html and remember that a slash “/” is used for comments. To read about the haml syntax in depth take a look at haml-lang. So simple sample of a page could be.
/Basic page structure with <html><head><title><body>
%html
%head
%title
Welcome
%body
/an h1 tag printing the name as it was assigned to the @name variable
%h1= "Hello #{@name}!"
/a strong tag with a class and id
%strong{:class => "code", :id => "myId"}
We love it here
/a similar strong tag using css style
%strong.code#message We really do!
/a basic content structure that consists of a div with of two colums which are also divs.
/the outer div with the id content and the children with classes defining them as columns left and right
#content
.left.column
%h2
Welcome to our site!
.right.column
Less helps you do more
Lastly we are pretty likely to need some css, and in this area I am a big fan of Less. Simply put Less is what css should have been - augmenting regular css with constructs such as variables and mixins. I covered this topic in a post some time ago.
By now it is probably no surprise that you start by installing a gem by running “gem install less”, and in your code you require 'less'.
.less files are then added to the views folder like this for example ./views/stylesheet.less. In this file you can use all the lessy goodness. This being ground I already covered a simple sample could be:
@color: #E41E1E;
div {color: @color;}
To allow yourself to use the file from a page you add an action that calls the less function:
get '/stylesheet.css' do
less :stylesheet
end
Now you can reference it from your haml file like this:
%link{:type => "text/css", :rel => "stylesheet", :href => "/stylesheet.css"}
Conclusion
Like the heading says I really like Sinatra. It is simple, flexible and provited me with a lot of control in what parts I choose to use along the way. I have only spent a few hours with it so far, and it has been a lot of fun. Doing a simple REST service wont get much more clean than with a framework like Sinatra.
That being said I have to be honest and admit that I probably won’t get to use it in my everyday job – after all we are a Microsoft shop and our world mostly revolves around C#, so it would not make much sense. Besides it being a Ruby framework, most of what we do is large scale solutions, so a light-weight framework was never intended for that kind of use.
Should I run into a situation where it would make sende there is an alternative, called Nancywhich is “a .NET framework inspired by Sinatra”. So I might give it a run some day – but at least for now I will stick with it as a plaything for a grown boy.