Sinatra Under the Hood

Sinatra is great. It’s a DSL (Domain Specific Language) for quickly creating web applications in Ruby, and its simple syntax and clear language make it ideal for basic and beginner web apps. With Sinatra, all it takes is a few lines to get off the ground with your very first web app, like this:

get ‘/’ do
‘Hello world!’
end

And presto! You have a web app that says “Hello world!” when someone accesses the home page. It’s really quite magical.

But how does Sinatra accomplish this magic? Mostly using unicorn hairs and a 10 oz of eye of newt. Also, Sinatra is built on top of Rack, and makes use of Rack’s capabilities.

Rack is a ruby gem that specifies a standardized interface for all web servers. Essentially, it allows our code to communicate with HTTP requests and respond accordingly. In fact, you could build a web app straight from Rack. A simple rack app has only one requirement: it respond to the call method. It will also return an array with three things: A status code, a header hash, and a body. Below is a simple rack app.

class Application
def call(env)
resp = Rack::Response.new
req = Rack::Request.new(env)
if req.path.match(/items/)
#some stuff
else
resp.write “Route not found”
resp.status = 404
end
resp.finish
end
end

A rack app takes in one argument, the environment (which includes all relevant information from the browser request), and makes that information available to us with a variety of built in methods and classes.

Here, we’re accessing the HTTP request using the Rack::Request object, and responding via the Rack::Response object. We have to manually check for the request type though, and manually set the status response. In Sinatra, we don’t have to do any of these things, which is part of why it is so much easier to use.

So how exactly is Sinatra using of Rack?

Behind the scenes, Sinatra is running a rack app that is taking in the env, and using the Rack::Request object to grab the .request_method and the .path_info. Then it’s matching up the request method with the methods that we constructed, and evaluating if the path matches. Finally, it’s executing the block in our method. In the case of our simple Sinatra controller above, that was just a string that said “Hello world!” Sinatra is also evaluating if the path was valid, and automatically returning an error status code if it was not.

This is a rather simplistic explanation, but it hopefully begins to give you an idea of what’s happening behind those gorgeous little lines, and gives you reason to tip your hat in thanks to the fine folks at Sinatra.

For a more thorough explanation, check out these resources: