Hatena::ブログ(Diary)

ursmの日記

2010-01-11

Rails 3 の Gem 管理ツール Bundler を使う

この記事は Bundler 0.8 について書いたものです。現行の Bundler 0.9 は API が大きく変わっているため、参考にしないでください。

新しい記事を書きました。 Rails 2.3.5 で Bundler 0.9.5 を使う - ursmの日記

Rails 3 では従来の Gem Dependencies (rake gems:*) に代わり Bundler という新しい Gem 管理ツールが導入されます*1。Gem Dependencies は安定性や使い勝手が今ひとつだったので、歓迎すべき変更といえるでしょう。Bundler には以下の利点があります:

  • 依存を再帰的に解決する
  • 環境を汚染しない。Gem はアプリケーションごとに独立してインストールされる
  • Rails アプリケーション以外でも使える。Sinatra や Rails 2 系でも OK

詳しい使い方は README を参照していただきたいのですが、簡単なメモを置いておきます。

インストール

% gem install bundler --source http://gemcutter.org

RubyGems 1.3.5 以降が必要です。

一般的な使い方

アプリケーションのルートディレクトリに Gemfile を作成します。

souce 'http://gemcutter.org'
gem 'sinatra', '0.9.4'
gem 'haml'

gem bundle で vendor/gems 以下に Gem がインストールされます。

% gem bundle
Calculating dependencies...
Updating source: http://gemcutter.org
(snip)
/home/ursm/hamlursmjp/bin/sass
/home/ursm/hamlursmjp/bin/css2sass
Done.
% ls vendor/gems/ruby/1.8/gems
haml-2.2.17/  rack-1.1.0/  sinatra-0.9.4/

vendor/gems/environment.rb が生成されているので、アプリケーションから require します。あとは普通に使えます。

require "#{File.dirname(__FILE__)}/vendor/gems/environment"
require 'sinatra/base'
require 'haml'
require 'sass'

class App < Sinatra::Base
  ...
end

Rails 2 系で使う

インストール先が vendor/gems のままだと Gem Dependencies と衝突するので、Gemfile に以下の行を追加して場所を変えます。

bundle_path 'vendor/bundler_gems'

config/preinitializer.rb を作成します。

require "#{File.dirname(__FILE__)}/../vendor/bundler_gems/environment"

config/boot.rb の末尾 (Rails.boot! の前) に以下のコードを挿入します。

class Rails::Boot
  def run
    load_initializer
    extend_environment
    Rails::Initializer.run(:set_load_path)
  end

  def extend_environment
    Rails::Initializer.class_eval do
      old_load = instance_method(:load_environment)
      define_method(:load_environment) do
        Bundler.require_env RAILS_ENV
        old_load.bind(self).call
      end
    end
  end
end

あとは gem bundle すれば動作します。

Rails 2 系との組み合わせでは Engines を使った Gem (Devise など) が動作しないようです*2。他は試したかぎり問題なさそうでした。

なお、Heroku も Bundler をサポートしています*3リポジトリのルートに Gemfile を置いて git push heroku master すると自動的に gem bundle が実行されます。

environments

gem 'rails' # (1)

only :development do
  gem 'rspec-rails' # (2)
end

only :production do
  gem 'mysql' # (3)
end
gem bundle
1, 2, 3 がすべてインストールされる
gem bundle --only development
1, 2 がインストールされる
gem bundle --only production
1, 3 がインストールされる
gem bundle --only development --only production
1, 2, 3 がすべてインストールされる
gem bundle --only hoge
1 がインストールされる

Bundler.require_env で指定された environment の Gem がロードされます。Rack アプリケーションなら以下のようにするのがいいでしょう。

require "#{File.dirname(__FILE__)}/vendor/gems/environment"
Bundler.require_env ENV['RACK_ENV']

require するファイルを変える

gem 'haml'                                 # require 'haml' も同時にやってくれる
gem 'ruby-openid', :require_as => 'openid' # 別のファイルを require する
# 配列を渡すと複数のファイルを require する
gem 'carrierwave', :require_as => %w(carrierwave carrierwave/orm/mongomapper)

Git リポジトリからインストールする

gem 'rubycas-client', :git => 'http://github.com/gunark/rubycas-client.git'

キャッシュ

ダウンロードした Gem は vendor/gems/ruby/1.8/cache にキャッシュされ、次に gem bundle を実行したときは (更新されてなければ) これが使われます。

gem bundle --cached の場合は更新を確認せずキャッシュを使います。

参考

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/ursm/20100111/1263219023