Ruby Sinatra Application

Sinatra is a lightweight framework to build web applications with Ruby.

Further Material

Topics, Tools and Terms

Ruby packages are called gems, and the tool to install new packages, called (gem), comes with the Ruby language distribution itself. gem lets us run install commands to add packages to our system, for example gem install rails will install Rails on our system.

Dependency Management

Having to install dependencies by hand quickly becomes tedious and time consuming. Luckily we have a tool called Bundler to help with that; Bundler needs to be installed as a gem: gem install bundler. This will install Bundler globally with the other gems on our system and provide the executable bundle for us which we’re going to use later.

Now we have a way to bundle and manage our dependencies in a file called a Gemfile. The content of that file is a list of gems we need for a given project. An example Gemfile looks like this:

source "https://rubygems.org"
gem "rails", "5.0.2"

The first line tells Bundler where to look for all gems. Rubygems.org is a central place where Ruby gems are available. The second line adds Rails as a dependency (with version 5.0.2). This is helpful to make sure every developer has the same versions installed on their systems. It is also helpful when we deploy our Ruby applications to a server for the same reason.

To have bundler installing everything needed for us we run bundle install. This will download all dependencies specified in the Gemfile.

Version Managers

Once you start working on more than one Ruby project a version manager will prove very beneficial.

Without a version manager we’d need to always install the currently needed version of Ruby for the project we’re working on. This isn’t so much a problem at the beginning, but once we work on one or two different projects that use different versions of Ruby it’s helpful to be able to just switch between versions.

We recommend using a version manager in order to be able to use different ruby versions on your system.

There are several version managers available: RVM, rbenv and chruby to name a couple of popular ones. They all solve the same problem and choosing one mostly boils down to personal preference.

A version manager will allow you to use different Ruby versions for different projects, so that you don’t always need to install a new Ruby version whenever you switch to a project that needs a different version. This can even be automated with a file named .ruby-version that contains the ruby version the project expects.

Testing Tools

For testing there are basically two options: Minitest or RSpec. Minitest follows the classic xUnit framework approach, whereas RSpec follows the behaviour driven design approach. Both frameworks are equally powerful and it boils down to personal preference which one you pick. In our guides we will be using RSpec as the default testing framework.

Directory Structure

Similar to the default directory structure for Ruby projects, Sinatra applications have a lib and spec directory. Additionally to that it is good practice to have a separate app (also sometimes called “web”) directory that encapsulates all Sinatra and web-related code like views or templates.

  • app
  • lib
  • spec
  • config.ru
  • Gemfile
  • Gemfile.lock

We provided a working example of a minimal Sinatra application on Github.

Important Files

Sinatra uses Rack, a standard interface for Ruby webservers, behind the scenes. Rack applications can be configured via a file called config.ru and started with the command rackup (the .ru ending stands for rack up).

Naming Conventions

File and directory names are in lower case and files match the classes or modules they contain. For example the class Vanilla should be contained in file vanilla.rb.

Tests match their production code file names with a _spec suffix, e.g. tests for code in lib/vanilla.rb should be written in spec/vanilla_spec.rb.

Example Project

The repository for an example applications is available at github.com/vanilla-project/ruby-sinatra.

The main building blocks of the application are the following three files:

  • config.ru runs the application by requiring:
    • app/application.rb that contains the main Sinatra application which itself requires
      • lib/example.rb to provide an example message that will be presented on the index page of the web application.

Running the Application

To start a Sinatra application we invoke: bundle exec rackup. When executing that, rackup will automatically look for the file config.ru as it is the default when no arguments are given. It will then print logging information similar to the following:

$: bundle exec rackup
[2017-07-13 07:20:01] INFO  WEBrick 1.3.1
[2017-07-13 07:20:01] INFO  ruby 2.3.1 (2016-04-26) [x86_64-linux]
[2017-07-13 07:20:01] INFO  WEBrick::HTTPServer#start: pid=26153 port=9292
...

This shows that the application is running and listening on port 9292. The host and port can also be configured via --host and --port arguments respectively.

Using a browser to navigate to http://localhost:9292 will then show the example page.

Running the Tests

To run all tests with RSpec we execute:

bundle exec rspec

This will execute the unit tests for all classes inside the lib directory as well as tests that exercise the actual Sinatra application.

Testing Approach

The test for class Example is only verifying the return value of one method.

Tests for the main Sinatra application on the other hand use rack-test to verify that the index page can be rendered successfully. This gem provides helper methods to exercise a Rack application during testing (e.g. get to send a GET request to the application). The benefit of using rack-test is that we don’t need to issue real HTTP requests to verify the application.