Bundlerで複数のGemfileを使う方法
通常、bundle exec
でgemを利用する時にはGemfileに必要なgemを列挙して利用するが、まれに複数のGemfileに分けたい場合もある。
ここでは例として、既存のRailsプロジェクトのGemfileに加えて別のgemを追加で読み込みたい場合を考える。
既存のGemfileは編集せずにそのままにしておいて、追加で必要なgemは別のGemfileで指定する。
方法
GemfileはRubyの内部DSLなので、Gemfileの中からもう一方のGemfileをevalすればよい。
追加で必要なgemは、別のディレクトリ(additional)に配置したGemfileに記載する。
ファイル構成は以下のとおりとなる。
project/
|- Gemfile # 既存のgemfile
|- 他のファイル
|- ...
additional/
|- Gemfile
additionalの中にあるGemfileを以下のように編集する。
eval_gemfile File.join( File.dirname(__FILE__), "../project/Gemfile")
gem "additional_gem" # 追加のgem
eval_gemfile
メソッドは、中のファイルを読んでinstance_evalしているだけ。
参考 : http://www.rubydoc.info/github/carlhuda/bundler/Bundler/Dsl:eval_gemfile
以降、additionalの中で bundle install
して、bundle exec
で実行すれば両方のgemが使えるようになる。
(追記) Gemfile.lockを使いたい場合は?
既存のプロジェクトがGemfile.lockを使ってバージョンを固定していたとする。
そのGemfile.lockに記載されたgemを使いたい場合、上記の方法ではうまくいかない。
上記の方法を利用するためには、Gemfile.lockからGemfileを構築するとできる。
require 'bundler'
lockfile = Bundler::LockfileParser.new(Bundler.read_file("Gemfile.lock"))
puts "source 'https://rubygems.org'"
lockfile.specs.each do |s|
puts "gem '#{s.name}', '#{s.version}'"
end
以下のスクリプトを既存のプロジェクトのGemfile,Gemfile.lockがあるディレクトリで実行する。
標準出力に、Gemfile.lockで指定されたバージョンに固定したGemfileができる。
このGemfileを上記の方法でevalすれば、既存のプロジェクトのgemを使うことができる。
参考情報
http://stackoverflow.com/questions/12237055/how-to-use-gems-not-in-a-gemfile-when-working-with-bundler
http://stackoverflow.com/questions/7962743/bundler-load-multiple-gemfiles