Blog tech

Thor - Simplifier les tâches récurrentes

Rédigé par Nicolas Cavigneaux | 12 mai 2011

Thor ?

Thor est en autre un remplacement de Rake. Ce framework permettant de faciliter la construction d’utilitaires en ligne de commande a été écrit par Yehuda Katz ce qui en dit déjà long sur la qualité de cet outil.

Thor a plusieurs avantages par rapport à Rake :

  • traitement des options de ligne de commande en toute facilité
  • génération automatique des aides d’utilisation
  • des helpers pour faciliter la manipulation du système de fichier, la création de templates, …
  • les tâches peuvent être installées pour être utilisées de n’importe où dans l’arborescence

Installation

Rien de bien nouveau :

gem install thor

Première tâche

On peut créer un fichier Thorfile (équivalent au Rakefile) qui contiendra nos tâches.

Un exemple des plus simple pourrait être :

class Test < Thor
  desc "bonjour", "Disons nous bonjour"
  def bonjour
    puts "Bonjour !"
  end
end

Si on essaie ensuite un thor list ou thor -T, nous verrons notre nouvelle tâche apparaitre :

test
----
thor test:bonjour  # Disons nous bonjour

Ajout d’un paramètre

Nos tâches sont tout à fait capable de recevoir des arguments. Plus besoin de passer par des variables d’environnement, Thor va gérer cela pour nous :

class Test < Thor
  desc "bonjour NOM", "Disons nous bonjour"
  def bonjour(nom)
    puts "Bonjour #{nom} !"
  end
end

Demandons de l’aide à Thor :

$ thor help test:bonjour

Usage:
  thor test:bonjour NOM

Disons nous bonjour

Essayons maintenant notre tâche améliorée :

$ thor test:bonjour Nico

Bonjour Nico !

Il est à noter que nous avons défini un paramètre, il est donc obligatoire de le spécifier lors de l’appel de la tâche. Si les paramètres obligatoires ne sont pas fournis, Thor s’en plaindra :

"bonjour" was called incorrectly. Call as "thor test:bonjour NOM".

Définir des options

Vous pouvez très facilement en plus des paramètres obligatoires, définir des options pour modifier le comportement de votre tâche :

class Test < Thor
  desc "bonjour NOM", "Disons nous bonjour"
  method_option :verbose, :aliases => "-v", :desc => "Parle plus que de raison"
  def bonjour(nom)
    puts "Bonjour #{nom} !"
    puts "Quelle belle journée." if options[:verbose]
  end
end

Essayons donc notre nouvelle option :

$ thor test:bonjour Nico -v

Bonjour Nico !
Quelle belle journée

Il est possible de définir plus finement les options :

method_option :path, :type => :string, :default => "~/", :required => false, :aliases => "-p"

Les types disponibles étant les suivants :

:boolean : --option / --option=true / --no-option

:string : --option=VALEUR

:numeric : --option=2

:array : --option=nico martin jr

:hash : --option=nom:Nico lang:ruby

Créer des dépendances entre tâches

Thor permet d’invoquer une tâche depuis une autre ce qui permet de chaines des appels et donc définir des dépendances :

class Compteur < Thor
  desc "un", "Affiche 1"
  def one
    puts 1
  end

  desc "deux", "Affiche 1, 2"
  def two
    invoke :un
    puts 2
  end

  desc "trois", "Affiche 1, 2, 3"
  def three
    invoke :deux
    puts 3
  end
end

La classe Thor::Group permet de produire le même type de comportement en exécutant toutes les méthodes du groupe, une à une, dans l’ordre de définition :

class Compteur < Thor::Group
  desc "Affiche 1 2 3"

  def un
    puts 1
  end

  def deux
    puts 2
  end

  def trois
    puts 3
  end
end
$ thor compteur
# => 1
# => 2
# => 3

Interactions utilisateur

Thor met à disposition un certain nombre de méthodes qui facilitent les interactions utilisateur. En voici quelque unes :

  • say
  • ask
  • yes?
  • no?
  • add_file
  • remove_file
  • copy_file
  • template
  • directory
  • inside
  • run
  • inject_into_file

Pour pouvoir les utiliser, n’oubliez pas d’inclure Thor::Actions dans votre classe.

Jetez un œil à la documentation de ces méthodes qui évitent de ré-inventer la roue.

Moi je veux un namespace pour la gloire !

Pas de problème, si vous avez besoin d’ajouter un namespace à vos tâches, rien de plus simple :

module Synbioz
  class App < Thor
    # taches
  end
end
$ thor synbioz:app:tache

System-wide !

Dernier gros avantage, lorsque l’une de vos tâches pourrait être ré-utilisé dans d’autres projets, inutile de recopier votre Thorfile dans chacun de vos projets. Il suffit, dans le répertoire contenant votre Thorfile, de lancer :

thor install Thorfile

Désormais, quelque soit le répertoire dans lequel vous vous trouvez, vos tâches sont disponibles !

Conclusion

Avec un tel framework, il devient très facile d’automatiser ses tâches récurrentes ou même encore de mettre rapidement en place un générateur comme on peut le connaitre dans Rails 3 (qui utilise Thor justement). On peut même à partir d’un Thorfile, créer une version exécutable avec très peu de modification.

L’équipe Synbioz.

Libres d’être ensemble.