À la découverte de Sinatra #1 - Hello World

Je l'ai déjà évoqué dans un précédent article : je suis un grand fan de Sinatra. Non, pas le chanteur (encore que !), mais plutôt la gem Ruby. En règle générale, j'aime utiliser des outils simples qui font bien ce qu'on leur demande, et je trouve que Sinatra correspond tout à fait à cette description. Pour être précis, Sinatra est présenté par ses auteurs comme un DSL qui vise à permettre la création d'applications web rapidement et sans efforts.

Sinatra web framework for Ruby

Pourquoi choisir Sinatra ?

En effet, quand on pense Ruby+Web, on pense tout de suite à Ruby on Rails. Mais Sinatra a de nombreux atouts à faire valoir face à ce mastodonte :

  1. Sinatra est petit (à peine plus de 2000 lignes de code, vous pouvez aller vérifier !), et par conséquent facile à appréhender. Sa rapidité de mise en place en fait un outil intéressant pour du prototyping, mais son extensibilité en fait également une solution pertinente pour propulser des sites petits ou moyens. À partir du moment où vous souhaitez développer des applications web plus complexes, je pense néanmoins qu'il est plus intéressant de regarder du côté de Rails.

  2. Sinatra est léger : lorsque j'ai commencé à m'y intéresser, je n'avais qu'un VPS de capacité limitée, le moindre Mo de RAM m'était précieux. Après quelques tests, j'ai pu constater que l'utilisation mémoire de Sinatra était bien plus contenue que celle de Rails (environ 30Mo pour Sinatra contre 120Mo pour Rails, pour une application simple utilisant une base de données sqlite). Contrairement à Rails, un nouveau projet Sinatra est vierge et ne comporte initialement que le strict minimum, à vous ensuite de l'enrichir avec les gems et middlewares dont vous avez besoin. Bref, je peux facilement faire tourner plusieurs applications Sinatra là où je ne pourrais avoir qu'une seule application Rails.

  3. Même si la communauté est loin d'être aussi importante que celle de Rails, il reste assez facile de trouver des informations, tutoriels et ressources sur Sinatra. En outre, le fait que Sinatra s'appuie sur Rack le rend facilement extensible avec les middleware Rack standard si vous ne trouvez pas de solutions ou gems spécifiques à Sinatra.

Hello World, the Sinatra way

Tout ça c'est bien joli, mais vous ne croyez que ce que vous voyez ? Alors développons ensemble un petit hello world en Sinatra.

Organisation du code source

Une application Sinatra consiste généralement en un fichier .rb qui contient l'ensemble des routes de votre application, et la façon dont elle doit répondre lorsqu'un utilisateur y accède. Par habitude, je nomme ce fichier app.rb.

Contrairement à Rails, Sinatra n'impose en effet pas de structure ou d'organisation de votre code source : vous pouvez même écrire une application Sinatra avec un seul et unique fichier (même si en conditions réelles, ça ne sera jamais le cas). En somme, c'est à vous d'organiser votre source de façon logique et maintenable. Aussi, gardez bien en tête que tout ce que je vous présente dans ce post et dans les suivants correspond à ma façon de faire.

Pour aujourd'hui, nous nous baserons sur la structure minimale suivante, que j'enrichirai dans les prochains articles :

1
2
3
4
5
6
7
8
9
10
sinatra-project
├── app.rb
├── Gemfile
├── public
│   ├── images
│   │   └── sinatra.png
│   └── stylesheets
│       └── app.css
└── views
    └── index.erb

Par défaut, Sinatra va chercher les templates dans le répertoire views, et les fichiers statiques (images, scripts, feuilles de styles, etc.) dans le répertoire public. C'est pour cette raison que notre projet est ainsi organisé, voilà, vous savez tout !

Gemfile

Avant toute autre chose, occupons-nous du Gemfile. Pour ce hello world, un Gemfile n'est même pas franchement nécessaire, mais autant commencer à mettre en place les outils qui nous accompagneront tout au long de la vie de ce projet :

1
2
3
# --- Gemfile ---
source 'https://rubygems.org'
gem 'sinatra'

Comme toujours, après ça, on lance un bundle install dans le terminal pour récupérer les dépendances… Ready to rock !

Passons au site en lui-même !

1
2
3
4
5
6
7
8
# --- app.rb ---
require 'sinatra'

# Lorsque l'utilisateur accède à la racine du projet, on affiche l'ERB "index.erb".
# Par défaut, Sinatra cherche le template dans le répertoire "views" à la racine du projet
get '/' do
  erb :index
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- views/index.erb -->
<!DOCTYPE html>
<html>
<head>
  <meta charset=utf-8 />
  <title>Hello World, the Sinatra Way</title>
  <link rel="stylesheet" type="text/css" media="screen" href="stylesheets/app.css" />
</head>
<body>
  <h1>Hello World, the Sinatra Way</h1>
  <p>
    If I can make it there<br/>
    I'll make it anywhere<br/>
    It's up to you<br/>
    New York, New York
  </p>
  <footer>
    <img src="/images/sinatra.png" />
  </footer>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* --- public/stylesheet/app.css --- */
body {
  color: #ccc;
  font-family: sans-serif;
  text-align: center;
}

h1 {
  color: #444;
  font-size: 3rem;
  font-weight: normal;
}

p {
  margin: 4rem auto;

  font-size: 2rem;
  line-height: 3rem;
}

Y'a plus qu'à !

OK, désormais, tout notre contenu est prêt. Il ne reste plus qu'à lancer un serveur de test pour vérifier que tout fonctionne. Pour aujourd'hui, on va faire simple et se contenter de la commande suivante :

1
2
3
4
5
$ ruby app.rb
== Sinatra (v2.0.1) has taken the stage on 4567 for development with backup from Thin
Thin web server (v1.7.2 codename Bachmanity)
Maximum connections set to 1024
Listening on localhost:4567, CTRL+C to stop

Un petit tour sur http://localhost:4567 et… twingo !

Hello World, the Sinatra way

Tout le code correspondant à ce premier article est disponible sur mon dépôt github pabuisson/blog-decouverte-sinatra, avec le tag partie-1. Les prochains articles donneront lieu à de nouveaux commits sur le même projet. Pour le récupérer et le lancer :

1
2
3
$ git clone git@github.com:pabuisson/blog-decouverte-sinatra.git
$ git checkout -f partie-1
$ cd blog-decouverte-sinatra && bundle && ruby app.rb

Références