#201 Bundler
Dans cet épisode, nous allons continuer de regarder les nouvelles fonctionnalités de Rails 3. Cette fois, nous allons voir bundler qui est le nouveau système de gestion de dépendances de gems pour les applications Rails.
Bundler est mis à jour souvent ces derniers temps. Prenez donc le temps de le mettre à jour avant de faire quelque chose avec. Vous pouvez vérifier que vous avez la dernière version en faisant :
gem install bundler
Notez que nous n'utilisons pas sudo
lorsque nous installons la gem parce que nous fonctionnons avec une version de Ruby installée avec rvm.
Utiliser Bundler pour installer des gems
Dans l'épisode précédent, quand nous avons essayé de lancer le serveur web de notre application, il s'est plaint de l'absence de la gem sqlite-ruby. Nous avons résolu ce problème en installant la gem à la main avec gem install
.
gem install sqlite3-ruby
Nous aurions pu cependant le faire grâce à bundler vu que sqlite3-ruby est une dépendance bundler de notre application (elle est listée dans le Gemfile
de l'application). Pour ce faire, nous appelons bundle install
qui va parcourir la liste des gems dont l'application dépend et les installer.
$ bundle install Fetching source index from http://gemcutter.org Resolving dependencies Installing abstract (1.0.0) from system gems Installing actionmailer (3.0.0.beta) from system gems Installing actionpack (3.0.0.beta) from system gems Installing activemodel (3.0.0.beta) from system gems Installing activerecord (3.0.0.beta) from system gems Installing activeresource (3.0.0.beta) from system gems Installing activesupport (3.0.0.beta) from system gems Installing arel (0.2.1) from rubygems repository at http://gemcutter.org Installing builder (2.1.2) from system gems Installing bundler (0.9.5) from system gems Installing erubis (2.6.5) from system gems Installing i18n (0.3.3) from system gems Installing mail (2.1.2) from system gems Installing memcache-client (1.7.8) from system gems Installing mime-types (1.16) from system gems Installing rack (1.1.0) from system gems Installing rack-mount (0.4.7) from rubygems repository at http://gemcutter.org Installing rack-test (0.5.3) from system gems Installing rails (3.0.0.beta) from system gems Installing railties (3.0.0.beta) from system gems Installing rake (0.8.7) from system gems Installing sqlite3-ruby (1.2.5) from system gems Installing text-format (1.0.0) from system gems Installing text-hyphen (1.0.0) from system gems Installing thor (0.13.1) from rubygems repository at http://gemcutter.org Installing tzinfo (0.3.16) from system gems Your bundle is complete!
Nous pouvons voir, dans l'affichage ci-dessus, que bundler a installé toutes les gems dont l'application a besoin, y compris sqlite3-ruby. Si elle n'avait pas été déjà installée, bundler l'aurait téléchargée depuis Gemcutter et l'aurait installée.
En clair, dans le doute, faites bundle install
. Vous devriez le faire chaque fois que vous créez une nouvelle application Rails ou que vous clonez l'application de quelqu'un d'autre. Cela vous assure d'avoir les bonnes gems installées. Vous devriez également le faire lorsque vous déployez une application de façon à ce que les gems soient installées sur le serveur. Vous pouvez même l'ajouter à vos recettes de déploiement pour que ça soit fait chaque fois que vous déployez votre application.
Il est important de noter que vous ne devriez jamais utiliser sudo
lorsque vous appelez bundle install
, même si vous utilisez sudo
d'habitude lors de l'installation de gems.
Ajouter des dépendances sur des gems
Maintenant que nous savons comment gérer nos gems, comment ajoutons-nous de nouvelles dépendances à notre application ? Dans les versions précédentes de Rails nous devions gérer cela dans le fichier /config/environment.rb
de notre application mais avec Rails 3, la configuration des gems se fait dans un fichier appelé Gemfile
à la racine de l'application. Le Gemfile par défaut ressemble à ceci :
# Edit this Gemfile to bundle your application's dependencies. source 'http://gemcutter.org' gem "rails", "3.0.0.beta" ## Bundle edge rails: # gem "rails", :git => "git://github.com/rails/rails.git" # ActiveRecord requires a database adapter. By default, # Rails has selected sqlite3. gem "sqlite3-ruby", :require => "sqlite3" ## Bundle the gems you use: # gem "bj" # gem "hpricot", "0.6" # gem "sqlite3-ruby", :require => "sqlite3" # gem "aws-s3", :require => "aws/s3" ## Bundle gems used only in certain environments: # gem "rspec", :group => :test # group :test do # gem "webrat" # end
Un certain nombre de gems est déjà présent dans le fichier, y compris rails
et sqlite3-ruby
. Notez que la ligne référençant la gem rails
inclue un numéro de version. Nous pouvons spécifier une numéro de version pour chaque gem pour choisir la version installée. Si nous voulons mettre Rails à jour, nous pouvons changer le numéro de version ici plutôt que dans le fichier environment.rb
.
Pour utiliser n'importe quelle gem supplémentaire dans notre application, nous devons juste les ajouter dans le Gemfile
. Par exemple, si nous voulons utiliser will_paginate, nous pouvons y faire référence comme ceci :
gem "will_paginate", ">=2.3.12"
Le second paramètre est un numéro de version et, utilisé ici, il signifie que bundler va installer la version 2.3.12 ou toute version plus récente trouvée. Une fois la référence à la gem ajoutée, nous pouvons l'installer avec bundle install
mais avant de le faire, nous allons montrer une autre commande de bundler, bundle check
.
Nous pouvons lancer bundle check
pour lister les gems dont notre application dépend mais qui ne sont pas installées. Si nous lançons cette commande pour notre application, elle va nous montrer que la gem will_paginate est référencée mais non installée.
$ bundle check The following dependencies are missing * will_paginate (>= 2.3.12, runtime)We can install the missing gems by running bundle install again.
Pour voir les autres commandes de bundle disponibles, nous pouvons lancer bundle help
.
$ bundle help Tasks: bundle check # Checks if the dependencies listed in Gemfile are satisfied by currently installed gems bundle exec # Run the command in context of the bundle bundle help [TASK] # Describe available tasks or one specific task bundle init # Generates a Gemfile into the current working directory bundle install # Install the current environment to the system bundle lock # Locks the bundle to the current set of dependencies, including all child dependencies. bundle pack # Packs all the gems to vendor/cache bundle show # Shows all gems that are part of the bundle. bundle unlock # Unlock the bundle. This allows gem versions to be changed
Les autres options du Gemfile
Retournons dans notre Gemfile pour voir ce que nous pouvons faire d'autre avec. Une nouvelle fonctionnalité sympathique, est la possibilité de récupérer une gem depuis un dépôt git. Par exemple, si nous voulons être à la pointe et utiliser la toute dernière version de Rails dans notre application, nous pouvons pointer sur son dépôt Git.
# Bundle edge rails: gem "rails", :git => "git://github.com/rails/rails.git"
C'est une fonctionnalité puissante. Si une gem ne fonctionne pas comme nous le souhaitons, nous pouvons créer un fork sur Github, modifier le code pour l'adapter à nos besoins et pointer sur notre dépôt pour utiliser notre version.
Nous pouvons également restreindre les gems à un certain environnement. Si nous voulons utiliser RSpec pour les tests, nous pouvons passer l'option :group
pour le restreindre à l'environnement de test.
gem "rspec", :group => :test
Dans le cas où nous avons un certain nombre de gems à restreindre à un environnement donné, nous pouvons utiliser group
et lui passer un bloc.
group :test do gem "webrat" get "rspec" end
Si nous lançons bundle install
maintenant, cela va installer toutes les gems ajoutées à cet environnement.
$ bundle install Fetching source index from http://gemcutter.org Resolving dependencies ... Installing rspec (1.3.0) from rubygems repository at http://gemcutter.org ... Installing webrat (0.7.0) from rubygems repository at http://gemcutter.org Installing will_paginate (2.3.12) from system gems Your bundle is complete!
Comme nous pouvons le voir sur l'affichage (tronqué) ci-dessus, deux gems de notre Gemfile
sont installées.
Si nous voulons installer des gems mais en excluant celles d'un certain environnement, nous pouvons utiliser l'option --without
. Pour installer les gems qui ne sont pas dans le groupe test, nous pouvons lancer :
bundle install --without=test
C'est utile lors de l'installation de votre application sur un serveur de production et que vous ne voulez pas installer les gems utiles uniquement pour les tests.
Verrouiller les gems
Une autre commande utile est bundle lock
. Cela verrouille les versions spécifiques des gems que votre application utilise. Après que nous l'ayons lancée, notre projet aura un nouveau fichier nommé Gemfile.lock
. Ce fichier liste toutes les gems installées pour notre application ainsi que les versions utilisées. Après avoir lancé bundle lock
, seules les versions listées dans le fichier Gemfile.lock
seront installées lorsque nous lancerons bundle install
, même s'il existe des versions plus récentes.
Vous pouvez vous demander quand vous pourriez avoir besoin de bundle lock
. Et bien c'est utile lorsque le projet est utilisé dans plusieurs endroits. Si nous travaillons avec d'autres développeurs web sur un projet, nous pouvons utiliser bundle lock
pour être sûr que tout le monde travaille avec les mêmes versions des gems utilisées par l'application. Cela est valable également lors du déploiement de l'application en production. Comme l'application est déployée sur un autre serveur, nous voulons être sûrs que les versions exactes des gems installées sur notre machine de développement soient utilisées sur le serveur de production.
Si nous avons besoin de modifier la liste des gems après avoir appelé bundle lock
, nous ne devons pas changer le fichier Gemfile.lock
directement. Nous devrions plutôt mettre à jour le fichier Gemfile
comme avant. Une fois nos changements effectués dans le fichier Gemfile
, lancer bundle install
ne va pas mettre les gems de l'application à jour puisque le Gemfile
est verrouillé. Pour mettre les gems à jour, nous devons passer l'option --relock
.
bundle install --relock
Cela va déverrouiller le Gemfile
, mettre les gems à jour et re-verrouiller.
Empaqueter les gems dans une application
Cela couvre à peu près le workflow basique de bundler et devrait vous donner assez pour travailler avec bundler dans vos applications. Une dernière fonctionnalité de bundler que nous allons voir est bundle pack
.
Bundler installe les gems dans un dossier .bundle
à la racine de notre compte.
$ ls ~/.bundle cache doc gems ruby specifications
Cela signifie que les gems ne sont pas embarquées dans notre application et ne sont pas inclues dans notre système de contrôle de versions. Si nous voulons stocker les gems dans notre application, nous pouvons lancer bundle pack
.
bundle pack Copying .gem files into vendor/cache * memcache-client-1.7.8.gem * rspec-1.3.0.gem * thor-0.13.3.gem * tzinfo-0.3.16.gem * builder-2.1.2.gem * nokogiri-1.4.1.gem * mime-types-1.16.gem * sqlite3-ruby-1.2.5.gem * i18n-0.3.3.gem * abstract-1.0.0.gem * erubis-2.6.5.gem * text-hyphen-1.0.0.gem * bundler-0.9.6.gem * rake-0.8.7.gem * will_paginate-2.3.12.gem * text-format-1.0.0.gem * rack-1.1.0.gem * rack-test-0.5.3.gem * webrat-0.7.0.gem * rack-mount-0.4.7.gem * activesupport-3.0.0.beta.gem * mail-2.1.2.gem * arel-0.2.1.gem * activemodel-3.0.0.beta.gem * actionpack-3.0.0.beta.gem * actionmailer-3.0.0.beta.gem * activerecord-3.0.0.beta.gem * activeresource-3.0.0.beta.gem * railties-3.0.0.beta.gem * rails-3.0.0.beta.gem
Cela va générer le fichier .gem
dont notre application a besoin et les copier dans son dossier /vendor/cache
, en créant le dossier si besoin. Les gems seront maintenant installées directement depuis ce fichiers .gem
au lieu d'être récupérées depuis, par exemple, Gemcutter.
Vous ne devriez pas en avoir besoin très souvent mais si vous êtes dans une situation où vous ne voulez pas que le serveur de production se connecte à Gemcutter pour télécharger les gems, c'est une bonne solution.
C'est tout pour cet épisode. J'espère que cela vous a donné un bon aperçu de comment bundler gère les gems de vos applications. Bundler peut prendre un peu de temps à appréhender mais il règle de nombreux problèmes liés à la gestion de dépendances que l'on pouvait rencontrer par le passé.
Nous terminerons en vous encourageant à visiter railsplugins.org. Vous vous demandez probablement quelles gems et quels plugins sont compatibles avec Rails 3. C'est l'endroit où trouver la réponse. Sur ce site, vous pouvez parcourir les plugins et voir s'ils fonctionnent avec Rails 3 et Ruby 1.9.
Si vous voulez utiliser une gem avec Rails 3 mais qu'elle est listée comme ne fonctionnant pas ou n'étant pas testée, c'est une bonne opportunité de lever des tickets ou d'aider à corriger cela. De cette façon, vous pouvez aider et vous impliquer dans l'effort fait pour que le plus de plugins et de gems soient compatibles avec Rails 3.