Ruby on Rake, ou comment Rake m'a rendu alcoolique
Je n’ai pas pour habitude de traduire les textes d’autrui, je ferai une exception pour cette fois sans rien y ajouter ni retrancher. D’abord parce que je ne vois pas ce que je pourrais dire de plus, ensuite parce que l’esprit même du texte rentre pour une bonne partie dans son intérêt, enfin parce que Rails manque trop de bonnes documentations en français, et que celle ci vaut le déplacement.
Ceci est la traduction de Ruby on Rails rake tutorial, de Greg Pollack.
Si vous développez en Ruby on Rail, vous avez certainement utilisé l’utilitaire Rake afin de lancer les tests, ou pour mettre à jour votre base de données en lançant rake db:migrate. Mais avez-vous vraiment conscience de ce qui se passe lorsque vous lancez une tâche Rake ? Savez-vous qu’il vous est possible de créer vos propres tâches rake, ou même de créer votre propre librairies de ces si pratiques descripteurs de tâches ?
Voici quelques cas d’usages des tâches Rake :
- Récupérer une liste d’inscrits afin d’envoyer un email.
- Lancer des traitements de calcul et de statistiques pendant la nuit.
- Supprimer et régénérer le cache d’une application.
- Sauvegarder ma base de données et mon dépôt subversion.
- Exécuter n’importe quel traitement de données.
- Me saouler la gueule.
Dans ce billet, vous allez découvrir le pourquoi de l’existence de Rake, et comment il peut vous aider dans le développement de vos applications Rails. À la fin de cette lecture, vous devriez être capable de créer vos propres tâches et de finir bourré comme un coing grâce à Rake en seulement trois petites étapes.
Pourquoi faire un retour en arrière ?
Pour comprendre les origines de Rake, il convient de s’intéresser un peu à son vénérable ancêtre, j’ai nommé Make.
Je vous propose un voyage dans le temps, à l’époque où le code devait obligatoirement être compilé, c’est à dire avant que l’iPhone et les langages interprétés ne parcourent la planète.
À cette époque, quand vous téléchargiez un logiciel, vous obteniez généralement des fichiers contenant le code source et un script shell. Ce script contenait tout ce que votre machine avait besoin de savoir afin de compiler, lier et construire votre application. Vous lanciez install_me.sh, chacune des lignes du fichier était exécutée, et vous obteniez au bout d’un moment un exécutable.
Ça marchait plutôt pas mal, il faut l’avouer, à part peut être pour les quelques développeurs de l’application. Chaque fois qu’ils changeaient la moindre ligne de code, il leur fallait relancer le script afin de tout recompiler. cela prenait évidemment un temps fou pour les gros logiciels.
En 1977, Stuart Feldman des laboratoires Bell inventa Make, qui résolut la majorité des problèmes liés aux compilations à répétition. Make est également utilisé afin de compiler des programmes, mais avec deux différences majeures :
- Make est capable de reconnaître quels fichiers ont été modifiés depuis la dernière compilation. Il pouvait donc ne compiler que ce qui avait changé d’une fois sur l’autre. Autant dire que cela a dramatiquement réduit les temps de compilation.
- Make peut aussi résoudre les dépendances. Il sait que pour être compilé, le fichier A a besoin du fichier B, qui lui-même a besoin de fichier C. Ce qui fait que si Make tente de compiler le fichier source A et que le fichier source B n’a pas été compilé, il commence par traiter ce dernier.
Je ne devrais pas continuer sans vous expliquer que Make est un simple exécutable, un peu comme “ls”, ou “dir”, et qu’il a besoin pour fonctionner d’un fichier annexe, appelé un “makefile”, qui va contenir toutes les sources et les dépendances du programme à compiler. Les “makefiles” ont leur propre syntaxe cabalistique qu’il ne nous sera pas donné de voir ici.
Au fur et à mesure, Make a évolué, et on a commencé à l’utiliser pour d’autres langages. En fait, de nombreux développeurs Ruby l’utilisaient avant l’avènement de Rake.
“Mais, Ruby n’a pas besoin d’être compilé, alors à quoi ça sert ?”. Vous ne l’avez peut-être pas dit, mais vous l’avez certainement pensé très fort.
Oui, je suis d’accord, Ruby est un langage interprété, et nous ne compilons pas notre code. Alors pourquoi utiliser Make ?
Eh bien, pour au moins deux raisons fondamentales :
- Automatiser des tâches : toute application d’envergure se termine presque fatalement par l’écriture de scripts à lancer en ligne de commande, qu’il s’agisse de lancer une maintenance, supprimer un cache ou faire évoluer la base de données. Et au lieu de créer une dizaine de petits scripts shell, ou un gros, vous pouvez aussi créer un seul “Makefile” dans lequel vous organiserez les choses à faire en tâches. Vous pouvez ensuite exécuter les tâches en lançant “make stupid”, c’est à dire littéralement “fait l’imbécile”, et cela lance la tâche “stupid”.
- Vérifier la résolution des dépendances entre les tâches. Quand vous lancez des opérations de maintenance en chaîne, vous en répétez fatalement certaines d’une tâche à l’autre. Par exemple, migrer une base de données et en faire une extraction ont toutes deux une connexion à la base pour prérequis. Vous pouvez donc créer une tâche de connexion qui sera lancée juste avant la migration.
Et Rake, dans tout ça ?
Il y a quelques années, Jim Weirich utilisait régulièrement Make sur un projet en Java. Tout en travaillant sur son Makefile, il réalisa combien il lui serait pratique d’avoir des bouts de Ruby dedans. Et Rake était né.
Jim donna à Rake la possibilité de réaliser des tâches, résoudre les dépendances, et même éviter de recommencer des tâches qui avaient déjà été réalisées. C’est évidemment quelque-chose que nous ne faisons pas vraiment, puisque Ruby n’est pas un langage compilé.
Comment ça marche ?
Imaginons que je veuille me saouler la gueule, quelles en seraient les étapes ?
- J’irais acheter à boire.
- Je me servirais à boire.
- Je boirais jusqu’à plus soif.
Si je voulais utiliser Rake pour chacune de ces tâches, je créerais un fichier nommé Rakefile, qui contiendrait quelque-chose comme ça :
Je peux maintenant lancer ces tâches depuis le répertoire où se trouve mon Rakefile, comme ça :
Sympa non ? Malheureusement, je ne vérifie pas que les tâches sont effectuées dans le bon ordre. Et bien qu’il puisse m’arriver de souhaiter être bourré avant d’avoir commencé à boire, ou même avant d’avoir acheté quoi que ce soit, ce n’est évidemment pas possible.
Rake et les dépendances
Maintenant, il me faut acheter à boire et me servir un verre avant de pouvoir me saouler la gueule convenablement. Cela donne donc :
Comme vous pouvez le voir, avant que je ne puisse boire, il me faut acheter de l’alcool et me servir un verre. L’ordre des choses est rétabli.
Avec le temps, vous risquez d’être tenté d’accroître votre alcoolisme, et donc votre Rakefile. Vous serez aussi certainement tentés de m’inviter à boire un coup. Comme dans tout logiciel d’envergure, rien ne vaut une bonne documentation.
Comment documenter mes tâches ?
Rake possède une manière très simple de documenter les tâches. Il s’agit de “desc” et c’est simple comme bonjour :
Comme vous pouvez le voir, chacune de mes tâches a maintenant une description. Mes amis peuvent les lire en tapant rake -T, ou rake --tasks.
Facile non ?
L’espace de nommage de Rake
Maintenant que vous êtes devenu un bon alcoolique, vous utilisez un grand nombre de tâches Rake, et vous avez besoin d’un bon moyen de les classer. C’est là que viennent les espaces de nommage. Si je devais utiliser un espace de nommage dans l’exemple précédent, il deviendrait :
Vous n’avez plus qu’à classer vos tâches en fonction des catégories, et OUI, vous pouvez en avoir plusieurs dans un même fichier. Maintenant, rake --tasks me donne :
Tu ne pourrais pas être un peu sérieux pour une fois ?
Les applications Rails viennent avec un lot de tâches prédéfinies, dont vous pouvez obtenir la liste en allant dans le répertoire de travail et en lançant rake --tasks. Si vous n’avez pas encore essayé, allez y, je peux attendre deux minutes…
Afin de créer une nouvelle tâche rake pour votre application Rails, vous devez dans un premier temps vous rendre dans le répertoire /lib/tasks (créé par défaut). Si vous y placez vos Rakefiles avec le suffixe “.rake”, celles-ci seront automatiquement récupérées par Rake. Nous allons ajouter la tâche suivante à notre application Rails.
Remarquez comment j’ai pu utiliser #{RAILS_ROOT} pour obtenir le chemin complet de l’application. Maintenant, si je lance rake --tasks dans le répertoire de mon application, je trouverai les nouvelles fonctions mélangées aux autres tâches Rake.
Génial ! Maintenant voyons comment ça devient vraiment utile.
Et on peux accéder aux modèles Rails depuis une tâche ?
Évidemment ! En fait, c’est même pour ça que j’utilise Rake : écrire des tâches que je lance à la main ou que je planifie en utilisant Crontab. Comme je le disais au début de l’article, j’utilise Rake pour les tâches suivantes :
- Récupérer une liste d’inscrits afin d’envoyer un email.
- Lancer des traitements de calcul et de statistiques pendant la nuit.
- Supprimer et régénérer le cache d’une application.
- Sauvegarder ma base de données et mon dépôt subversion.
- Exécuter n’importe quel traitement de données.
- Me saouler la gueule.
Sacrément utile, et facile qui plus est. Le code suivant récupère la liste des utilisateurs dont l’abonnement arrive à expiration et leur envoie un courriel :
Comme vous pouvez le voir, nous accédons au modèle en deux étapes : la directive require et le => :environment.
- require File.expand_path(File.dirname(__FILE__) + “/../../config/environment”)
- task(:send_expire_soon_emails => :environment) do
Pour lancer ça tous les soirs à minuit, je n’ai qu’à créer une tâche dans Crontab, de cette manière :
Où trouver plus d’exemples ?
Maintenant que vous en savez assez pour écrire des tâches utiles, je me suis dit que je pourrais vous laisser repartir avec quelques ressources supplémentaires. La meilleure manière de vous améliorer est encore de lire le code des autres, comme ces tâches Rake :
- Ces nouvelles tâches incluses dans Rails Edge remettent votre base de données à zéro pour vous.
- Craig Ambrose a écrit une tâche pour sauvegarder votre base de données.
- Adam Greene a écrit une série de tâches qui vous permettent de sauvegarder vos données sur Amazon S3.
C’est fait. Si vous en connaissez d’autres, n’hésitez pas à les publier dans les commentaires.
Toujours là ? Ça tombe bien, les gens de RailsEnvy à qui nous devons cet excellent article cherchent de nouveaux collaborateurs. Contactez Greg at RailsEnvy si ça vous intéresse.

Commentaires
Trackbacks
Les trackbacks sont fermés pour cause de spam.

Passionné d'informatique depuis l'âge de six ans, je travaille en tant que responsable qualité chez blueKiwi Software, éditeur spécialiste des outils collaboratifs en entreprise. Ma double formation en sciences politiques et en informatique me permet de porter un regard particulier sur les problématiques abordées par mon poste.
AlSquire about 3 hours later:
Merci pour cette tradu… nan en fait j’ai déjà la version anglaise imprimée sur le bureau, par contre j’ai une super blague :
Tâche sans accent, ça fait tache !…
Xethorn about 11 hours later:
Article intéressant qui, sur de nombreux points, me rappelle la programmation Smalltalk !
Sinon, la prochaine fois que tu fais un article, laisse le côté “je bois”, ça rajoute du punch à l’ensemble. C’est bien mieux qu’une théorie de bois ;)
PoMM3 about 14 hours later:
Merci Frédéric.
Encore un morceau de documentation Ruby éparpillé dans l’Internet…
C’est vraiment le gros défaut de Ruby qui a subi son expansion dans l’ère du 2.0 ce qui donne une documentation “blog style” et “screen cast style”.
Php bénéficiait d’une centralisation de la documentation sur son portail ce qui en a fait sa force.
Frederic de Villamil about 14 hours later:
Oups, j’ai effectivement laissé passer quelques fautes d’orthographe ici et là… faut dire que je l’ai traduit un peu à la volée et sans relire… ça m’apprendra.
Pomme : c’est une des forces et des faiblesses de Rails : reposer sur une communauté de passionnés. Et pour le reste, tu as api.rubyonrails.org
PoMM3 about 15 hours later:
J’ai une petite préférence pour http://www.railsapi.org/ qui j’espère sera plein d’avenir. Mais j’utilise api.rubyonrails.org quand j’approfondis.
Samuel MARTIN about 21 hours later:
Vraiment très intéressant cet article ! C’est super clair, merci