Last Updated:

Just Do It: Learn Sinatra

Welcome to the last part of this series. The goal of this tutorial series was to take someone who has never used Sinatra from creating an application to deploying it. You can find other parts of the series at the following links:

After these three parts, we've completed most of the basic features of our to-do list. In this final part, we'll look at using Sass for CSS before deploying the application to Heroku cloud hosting.

Logotype

 

Every self-respecting app needs a logo, so I've created a simple "tick" logo that you can find on Github. We can use this in the app by setting it as the background image of the main header. Open the styles file.css and add the following CSS:

 

h1.logo{
  font-family: helvetica,arial,sans-serif;
  font-size: 24px;
  color: white;
  padding: 64px 0 0;
  margin: 0 auto;
  text-transform: uppercase;
  text-align: center;
  font-weight: normal;
  letter-spacing: 0.3em;
  background: transparent url(/logo.png) 50% 0 no-repeat;
  }

 

(Note: If you don't notice, you'll need to add the 'logo' class to the h1 element in layout.slim for this to work)

 

I also used the logo to create the icon, which you can also find on Github. To display this, you'll need to add a reference to it in the HTML. This means that layout.slim should now look like this:

 

doctype html
html
  head
    meta charset="utf-8"
    title Just Do It!
    link rel="shortcut icon" href="/favicon.ico"
    link rel="stylesheet" media="screen, projection" href="/styles.css"
    /[if lt IE 9]
      script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"
  body
    h1.logo Just Do It!
    == yield

Cheeky

 

Sass (Syntaxically Awesome Stylesheets) is a CSS template language that means you write your styles in Sass, which is then compiled on the server side into CSS that is sent to the browser. It's very cool and that's basically all the CSS was supposed to be. There are two kinds of Sass – the original "Indented Sass" and the later "SCSS" (Sassy CSS). I'm going to use SCSS as it's more like regular CSS, but it's definitely worth trying both and seeing which one you prefer.

 

To include Sass in your Sinatra project, we need to install the Sass Stone:

 

gem install sass

Next, we need to add the following handler to the end of main.rb:

 

get '/styles.css' do 
  scss :styles
end

This basically takes a reference to the styles.css file we already have in our layout file and loads a Sass file named 'styles.scss'. This file doesn't exist yet, so create one. It should be stored in the 'views' directory. Copy the contents of the styles.css file (in the shared folder) to the styles.scss file, and then delete the styles.css file.

If you look at how the app looks in a browser, nothing should have changed. This is because SCSS is a superset of CSS, so any regular CSS will work as expected, so all we just did was move from using standard CSS to Scss. But now we're ready to start turbocharging our styles.

CSS variables

 

One of the most requested elements in CSS wish lists are variables. Sass gives us the ability to use variables. For example, we can set colors using variables that are referenced in the markup.

$orange:#D78123;
$blue:#1E1641;
$green:#02d330;
$grey: #999;

Now we can reference these colors in the rest of the style sheet. For example, to make the headings in each list orange, I can write the following in styles.scss:

.list h1{
  color: $orange;
}

This makes the maintenance much easier, as if a number of elements were using this color, and then I decided to make it a little darker, I only need to change it in one place. There's a lot you can do with variables, including arithmetic – be sure to check out the documentation.

CSS Mixins

Mixins are a really cool feature of Sass that allows you to create modular and reusable CSS. For example, we'll create a mixin called a button that contains all the relevant CSS to turn a standard link into a button:

 

@mixin button($color){
    background:$color;
    border: 2px solid darken($color,15%);
    cursor: pointer;
    color: #fff;
    width: 150px;
    margin-left:4px;
}

Now I can add these generic styles to any other CSS declaration in my style sheet using @include

.button{
    @include button($orange);
    }

This will add all the CSS from the mixin button to any element with the button class. Of course, we could just write CSS directly in the 'button' class, but using a mixin allows us to add it to any other CSS declaration without repeating any code. Also note that the mixin includes a color argument that allows you to use multi-colored buttons without having to repeat the code. Also note that we were able to use the orange color that was contained in the variable $orange

 

Nested CSS

Another interesting feature of Sass is the ability to attach your ads. This can save a lot of printing and add more structure to your CSS file.

For example, the following CSS was used to style the lists and headings in each list:

.list{
  float: left;  
  background: #fff;
}
.list  h1{  
    color:$orange;
}

This can be written more effectively by nesting the h1 declaration in the .list declaration, for example:

.list{
  float: left;  
  background: #fff;
  h1{  
    color:$orange;
  }
}

The above Scss will compile with the same CSS as in the example above, but has the advantage of showing a nested structure. It can also save a lot of text if you start using deeply nested CSS.

Sass is such a powerful tool that makes writing CSS a lot easier, and it's so easy to implement in Sinatra that there's really no reason not to use it in all your projects. Especially since you can just write a standard CSS and include additional "cheeky" features as needed. I've given a few examples here that are just beginning to touch the surface that Sass is capable of. I'd encourage you to familiarize yourself with this, read the documentation, and most importantly, play around with your own code. I promise that once you start using Sass, you won't go back to regular CSS!

 

There's not enough space to display the full Scss file, but you can see the full code on Github. Now that we're done with the app, it's time to deploy it.

Heroku

Heroku is a great service that you can use to host Sinatra applications in the cloud. It's free for basic sites, includes database storage, and will scale as your app becomes more popular It takes all the hassle off hosting sites and can be used for large-scale production sites. They also have excellent documentation and support.

The first thing you need to do if you don't already have one is get a Heroku account. Next, make sure your system has Git installed. If not, there's a helpful guide to Github. Be sure to pay special attention to the section on configuring SSH keys, as you will need them to access Heroku.

Next, you need to install the Heroku gem, which will allow you to interact with your apps on Heroku:

gem install heroku

If you're using Heroku for the first time, you'll need to add the newly created SSH keys (you only need to do this once):

heroku keys:add

Now we can create an application on Heroku:

 

heroku create justdoit

(Note that you'll have to use a different name for your app, as justdoit is already taken by me!)

Now that you've set up Heroku, it's time to prepare your app for deployment.

Bundler

Before we deploy the application to Heorku, we need to use the Bundler to manage all the dependencies that are in our application. These include all the gemstones we have used, as well as the gemstones they depend on. Bundler installs all these gems directly into the app's catalog. This means that your app comes "bundled" with all of its dependencies, so you don't rely on having anything installed on the default server (in any case, Heroku literally doesn't have any gems by default). You can also manage the version number of any gemstones to ensure that the versions used in production match the versions used in development.

First, we need to install the Hem Bundler:

gem install bundler

Now we need to create two new files in the main application folder. First of all, we need a Gemfile that lists all the gemstones we've used. Save the following code in a file named Gemfile (without the extension) in the root directory of your application:

source :rubygems
gem "sinatra"
gem "datamapper"
gem "slim"
gem "sass"
gem "dm-postgres-adapter", :group => :production
gem "dm-sqlite-adapter", :group => :development

The last two lines specify the database adapters that the Datamapper uses to connect to the database. So far, we've used Sqlite on our development machine, but Heroku uses PostgreSQL. Using different databases in different environments is accomplished by placing the database adapter gems in what the Bundler calls groups.

We also need a Rackup file. Open your text editor and save the following as config.ru:

require 'bundler'
Bundler.require
require './main'

DataMapper.setup(:default, ENV['DATABASE_URL'] || "sqlite3://#{Dir.pwd}/development.db")

run Sinatra::Application

Note that I placed the database connection string in this file—this file usually puts the configuration code. This means that you should now remove this string from main.rb.

Finally, you need to test this locally, so we run the bundle install command.

bundle install --without production

Flag --without production

There is no need to run this command in working mode – Heroku will start it automatically if it detects Gemfile. However, we have to tell Heroku to avoid using any gemstones in the "development" group. This is done with a simple command:

heroku config:add BUNDLE_WITHOUT="development:test" --app justdoit

(note that you will have to use your app name instead of justdoit)

Before we move on to deploying the application, we just have to make sure that everything is working fine on our local machine. It's done differently now that we have a rack file. Open a Command Prompt window, and then type the following:

rackup

This will start the server on port 9292. Go to http://localhost:9292/ to see what it looks like.

deployment

All that's left is to deploy the app to Heroku. First of all, we need to create a file named .gitignore, which is saved in the root directory and contains the following 2 lines:

development.db
.bundle

This will stop any unnecessary files being added to the git repository. We don't want the Sqlite database file to be in the git repository because Heroku doesn't use it. We also don't want the .bundle directory to be sent to the production server (as it will have its own version).

The next task is to initialize the Git repository:

git init
git add .
git commit -m 'initial deployment'

Finally, we add the app to Heroku

git push heroku master

As you develop your app, it's very easy to update the code in Heroku. This is simply the case of uploading code to a Git repository and then uploading it to Heroku using the following commands:

git add .
git commit -m 'some message about the updates'
git push heroku master

All that's left is to configure the database on the server by performing the migration. The Heroku CLI allows you to access the irb console, which allows you to interact with your app:

heroku console
Ruby console for justdoit.heroku.com
>> DataMapper.auto_migrate!

You can open the site from the command line using the following command:

heroku open

This should lead you to your live app. You can see my finished version of Just Do It! - Don't hesitate to play with him. I also put all the source code on github so you can view all the files in their entirety.

It's all people.

And that concludes this four-part series. I hope he's given you enough information to get started with Sinatra, as well as a desire to learn more. Of course, the best way to learn is to experiment on your own, and Sinatra has such a low barrier to entry, making it incredibly easy to launch new apps and play with code. I would like to know if any of you want more articles about Sinatra and what you would like to see covered – leave any feedback in the comments.