Démarrer un projet basé sur Ruby 💎

Tiens ! Si je jetais un œil à mon blog ? Mince, j’ai changé de PC depuis la dernière fois… Ah ! Il faut que j’installe Ruby 💎🤔…
— Bibi

Ce blog utilise Jekyll, générateur de site statique en Ruby. Ce n’est pas un environnement technique que j’utilise au quotidien et ce blog est mis à jour suffisamment rarement pour que le garbage collector de ma mémoire ait malheureusement fait son office.

Le temps passé à réinstaller toute la stack justifie donc l’écriture d’un article « pense-bête », une sorte de B-A, BA [1] de l’installation d’une stack Ruby 💎 dans un environnement Linux.

Cet article est loin d’être exhaustif sur l’environnement Ruby. Il ne fait qu’aborder une infime partie des outils et commandes proposés par la stack.

Le spectre d’outils évoqué ici suffit pour un projet basé sur un framework nécessitant un environnement Ruby (Jekyll, Asciidoctor…), mais n’est clairement pas suffisant pour se lancer dans un réel développement en language Ruby.

RVM (Ruby Version Manager)

J’aurais pu me contenter d’un sudo apt install ruby, mais tout comme je suis parfois amené à jongler entre plusieurs version de Node.js, je pourrais avoir à gérer plusieurs versions de Ruby selon les projets dans lesquels je me lance. C’est là qu’intervient RVM.

RVM est à Ruby ce que NVM est à Node.js. Il permet de gérer sur un même OS plusieurs environnements d’exécution Ruby. De multiples interpréteurs sont disponibles à l’installation (Ruby MRI, JRuby…), chacun disponible dans plusieurs versions.

L’outil permet également d’isoler les dépendances tierces des projets Ruby à l’aide de gemsets, que je n’aborderais pas ici, préférant gérer les dépendances de chacun de mes projets au sein de ceux-ci.

Installation

L’installation se fait en une commande :

$ curl -sSL https://get.rvm.io | bash -s stable

Si comme moi vous n’aimez pas qu’on trifouille dans vos fichiers de configuration (.bashrc, .profile, etc.), vous pouvez exécuter la commande d’installation avec l’option --ignore-dotfiles

$ curl -sSL https://get.rvm.io | bash -s -- --ignore-dotfiles

Mais charge à vous ensuite d’ajouter comme il vous sied les instructions nécessaires au bon fonctionnement de RVM

Quelques commandes utiles

La documentation de RVM est dense, très dense. Voici donc, en synthèse, les quelques commandes que j’utilise le plus fréquemment :

Lister les versions de Ruby disponibles à l’installation
$ rvm list known
Installer une version de Ruby
$ rvm install <VERSION>
Sélectionner une version de Ruby par défaut
$ rvm --default use <VERSION>
Sélectionner une version de Ruby pour un projet
$ rvm --ruby-version use <VERSION>

L’option --ruby-version, optionnelle, permet de sauvegarder la version spécifiée dans la commande dans un fichier .ruby-version du répertoire courant.

Ainsi inutile à l’avenir de spécifier la version en paramètre. La commande suivante, exécutée dans le répertoire projet, suffira à charger l’environnement :

$ rvm use
Mettre à jour RVM
$ rvm get stable
Faire le ménage
$ rvm cleanup all

Cette commande se révèle particulièrement utile si votre répertoire ~/.rvm prend de l’embonpoint [2] .

Gestion des dépendances

En Ruby, les dépendances sont appelées des gems, et l’outil de prédilection pour les gérer est Bundler. Pour continuer dans les analogies avec Node.js, Bundler est un peu le NPM de Ruby. Tout comme NPM avec Node.js, l’outil est lui aussi disponible après l’installation d’un environnement Ruby avec RVM.

Les dépendances d’un projet sont spécifiées dans un fichier Gemfile [3].

Voici une liste non-exhaustive des commandes proposées par Bundler :

Installer les dépendances [4]
$ bundle install

Cette commande interprète le contenu du fichier Gemfile pour télécharger et installer les dépendances qui y sont indiquées, ainsi que les dépendances transitives.

Lors de la première exécution la commande génère un fichier Gemfile.lock dans lequel on retrouve la liste exhaustive des gems installés ainsi que la version précise de chacun.

Si un fichier Gemfile.lock est présent lors de l’exécution de la commande, il n’y a pas de résolution des dépendances. La commande installe simplement les gems indiqués dans le fichier.

Comme évoqué plus haut, j’aime bien disposer des dépendances de mon projet directement dans celui-ci (les habitudes de travailler avec Node.js 🤷‍♂️). La commande bundle supporte des paramètres qui permettent de répondre à ce besoin :

$ bundle install \
    --path=.bundle/gems \(1)
    --binstubs=.bundle/.bin(2)
1 Indique à Bundler de télécharger les gems dans le répertoire .bundle/gems.
2 les exécutables des gems seront placés dans le répertoire .bundle/.bin.

les valeurs données à path et binstubs sont sauvegardées dans un fichier .bundle/config. Inutile donc de spécifier ces options à chaque exécution de bundle install.

Mettre à jour les dépendances [5]
$ bundle update --all(1)
1 L’option --all force Bundler à résoudre les dépendances en ignorant les gems précédemennt installés, et à regénérer le Gemfile.lock.

La commande bundle update respecte toujours les versions de gems indiquées dans le fichier Gemfile. Il faut donc modifier manuellement le fichier pour s’assurer de télécharger les versions souhaitées des dépendances.

Pour lister les gems dont les versions pourraient être mises à jour dans le fichier Gemfile, utiliser la commande suivante [6] :

$ bundle outdated | grep requested

Démarrer un nouveau projet

Le moment est venu de mettre en œuvre les quelques commandes passées en revu jusqu’ici.

Nous prendrons comme exemple la création d’un nouveau projet de documentation utilisateur écrit en Asciidoc à l’aide de la librairie asciidoctor.

  1. Créer le répertoire projet

    $ mkdir some-documentation-project && cd some-documentation-project
  2. Charger l’environnement Ruby

    $ rvm --ruby-version use 2.6

    La version de Ruby souhaitée doit évidemment avoir été installée au préalable avec la commande suivante :

    $ rvm install 2.6
  3. Initier un nouveau fichier Gemfile

    $ bundle init
  4. Ajouter la dépendance à asciidoctor

    $ echo "gem 'asciidoctor', '~> 2.0.10'" >> Gemfile

    La manière dont est spécifié la version du gem asciidoctor utilise l’opérateur pessimiste ~>, aussi appelé twidlle waka [7]. Dans le cas présent celui-ci permet de spécifier qu’on souhaite travailler avec la version d'asciidoctor la plus haute dans la plage ≥ 2.0.10 et < 2.1.

  5. Télécharger les dépendances du projet

    $ bundle install --path=.bundle/gems --binstubs=.bundle/.bin
  6. Travailler

  7. Profits [8] !


1. Expression totalement désuète dont j’ai découvert l’étymologie lors de l’écriture de ce post (voir https://fr.wiktionary.org/wiki/b.a.-ba#fr). Du coup je l’ai conservée 😊.
2. Faire le ménage dans RVM : https://coderwall.com/p/x3z2ag/cleanup-rvm
3. Description du fichier Gemfile : https://bundler.io/man/gemfile.5.html
4. Description de la commande bundle install : https://bundler.io/v2.0/man/bundle-install.1.html
5. Description de la commande bundle update : https://bundler.io/v2.0/man/bundle-update.1.html
7. Ruby’s Pessimistic Operator : https://thoughtbot.com/blog/rubys-pessimistic-operator
8. Voir l’épisode S02E17 de South Park « Les Gnomes voleurs de slips » : https://i.kym-cdn.com/entries/icons/original/000/000/248/profit.jpg