bundlerでgemをプロジェクトごとに管理する
前回ではrubyの環境を構築しました。
今回はプロジェクトごとにgemを管理する方法をご紹介したいと思います。
gemとは
rubyではライブラリやフレームワークをgemというパッケージにして再利用ができ、
rubygemsという管理ツールでインストールやアップデート、アンインストールが可能です。
これは他の言語にも同じようなシステムが存在します。
- Python の PyPi
- Perl の CPAN
- Node の npm
ruby 1.9からはrubygemsは標準で組み込まれるようになったので特に準備は必要ありません。 またgemはrubygems.orgにて検索が可能です。
rubygemsを使ってみる
rubygemsのコマンドはgemです。以下によく使うコマンドとオプションを載せておきます。
gemをインストールする
$ gem install (gem name)
デフォルトではドキュメントも一緒にインストールされます。しかしインストール時間が長くかかってしまうので省くオプションをつけることもできます。
$ gem install (gem name) --no-ri --no-rdoc
gemをアップデート
$ gem update (gem name)
gemをアンインストール
$ gem uninstall (gem name)
インストール済みのgemの一覧を出力
$ gem list
インストール済みのgem一覧をブラウザでも確認できます
$ gem server
gemコマンドのヘルプ
$ gem help (command)
bundlerを使う
Bundler: The best way to manage Ruby applications
さて本題のbundlerを使用したgemの管理方法に触れたいと思います
bundler自体もgemですのでまずはインストールします。
$ gem install bundler --no-ri --no-rdoc
インストールができたら作業ディレクトリに移動し初期化コマンドを実行します。
bundlerのコマンドはbundleです。
$ bundle init Writing new Gemfile to /path/to/project/Gemfile
Gemfileという名前のファイルが作られました。
これは使用するgemをrubyで記述して、バージョンを指定したり環境ごとにグループ分けができるようになります。
例えばスクレイピングのライブラリであるMechanizeを使う場合は以下のように記述します。
source "https://rubygems.org" gem 'mechanize', '~> 2.5.1'
一行目にはgemがホスティングされているサーバを記述します。基本的にはrubygems.orgで問題ありません
次にgemメソッドの第一引数に名称、第二引数は省略も可能ですがバージョンを指定しています。
~>は2.5.1以上で2.6未満の最新を指定しています。
他にも>=や<などが使えますが詳しくはこちらのページを御覧ください。
Gemfileに記述しただけではまだ使用できませんのでインストールを実行します。
また今回はプロジェクトごとにというのが目的ですのでvendor/bundleフォルダをインストールパスに指定しました。
フォルダは事前に用意しなくてもbundlerが作成してくれるので大丈夫です。
$ bundle install --path vendor/bundle Fetching full source index from https://rubygems.org/ Installing unf_ext (0.0.5) with native extensions Installing unf (0.0.5) Installing domain_name (0.5.4) Installing mime-types (1.19) Installing net-http-digest_auth (1.2.1) Installing net-http-persistent (2.8) Installing nokogiri (1.5.5) with native extensions Installing ntlm-http (0.1.1) Installing webrobots (0.0.13) Installing mechanize (2.5.1) Using bundler (1.2.1) Your bundle is complete! It was installed into ./vendor/bundle
依存ライブラリも含めてvendor/bundleフォルダにインストールされました。
そしてmechanizeを使ったサンプルを作成してみます。このブログのトップページにアクセスしてtitleタグの中身を出力してみるようにしました。
require 'mechanize' agent = Mechanize.new agent.get('https://dev.classmethod.jp/') puts agent.page.title
そしてこのrubyスクリプトを実行してみましょう。通常であれば ruby sample.rb などとします。
しかしmechanizeはシステムにインストールされていませんので、エラーしてしまいます。
プロジェクトローカルな環境で実行するには以下のようにします。
$ bundle exec ruby sample.rb AWS, iPhone, Android, HTML5に関する情報発信 | クラスメソッド開発ブログ
bundle exec をつけることで問題なく動作しました。
githubにあるgemを使う
githubに限りませんがgitリポジトリからインストールもできます。
gem "foo", :git => "https://github.com/bar/foo.git"
環境別にgemを管理する
テストフレームワーク等プロダクション環境には必要ないgemがある場合はgroupを使うと環境別にgemを管理できます。
例えば以下のように記述しbundle install時にオプションをつけることで実現できます。
source "https://rubygems.org" gem "mechanize", "~> 2.5.1" group :development, :test do gem "rspec" end
$ bundle install --path vendor/bundle --without development test
このようにインストール時に指定したオプションは.bundle/configというファイルに保存されていますので、gemを追加した場合など2回目以降では省略できます。
またこれらのオプションは以下のコマンドで確認できます。
$ bundle config Settings are listed in order of priority. The top value will be used. path Set for your local app (/path/to/project/.bundle/config): "vendor/bundle" disable_shared_gems Set for your local app (/path/to/project/.bundle/config): "1" without Set for your local app (/path/to/project/.bundle/config): "development:test"
bundle install後にはプロジェクトフォルダに Gemfile.lock というファイルが作られています。これはGemfileに記述したバージョンが曖昧だった場合でも実際にどのバージョンをインストールしたのかが示されています。
これによって別に環境を構築する際にも同じ状態が作れるようになります。
gemをアップデートする
新しいバージョンがリリースされたらGemfileのバージョンを書き換えて、bundle updateを実行します。
単体のgemの指定もできます。
gem "mechanize", "~> 2.6" # 2.6がリリースされたと仮定
$ bundle update mechanize
オフライン環境でもbundle installできるようにする
プロダクション環境は外部ネットワークに出られないといったこともあるかもしれません。そういった場合にも対応できるようなオプションも存在します。
以下のように bundle package を使うと vendor/cache フォルダにgemをキャッシュします。
$ bundle package Using unf_ext (0.0.5) Using unf (0.0.5) Using domain_name (0.5.4) Using mime-types (1.19) Using net-http-digest_auth (1.2.1) Using net-http-persistent (2.8) Using nokogiri (1.5.5) Using ntlm-http (0.1.1) Using webrobots (0.0.13) Using mechanize (2.5.1) Using bundler (1.2.1) Your bundle is complete! It was installed into ./vendor/bundle Updating files in vendor/cache * unf_ext-0.0.5.gem * unf-0.0.5.gem * domain_name-0.5.4.gem * mime-types-1.19.gem * net-http-digest_auth-1.2.1.gem * net-http-persistent-2.8.gem * nokogiri-1.5.5.gem * ntlm-http-0.1.1.gem * webrobots-0.0.13.gem * mechanize-2.5.1.gem
オフライン環境では --local オプションを付けることでrubygems.org等を見に行かずに、vendor/cacheフォルダを見るようになります。
$ bundle install --local
まとめ
bundlerには他にもbundler自体がインストールされていない環境でも動かせるようにするオプション(--standalone)等、便利な機能がたくさん用意されています。
大まかにはGemfileを元にインストールとロードパスを通すのが役目です。
ちょっとだけ試してみたいgemがあるときにも気軽に使えるようになると思うので是非活用してみてください。