アプリケーション本体や自動テストを実行するのに必要なgemは、開発者全員が同じものをインストールするべきだ。しかし、pry-*などの開発支援系のgemについては、開発者全員が同じものを使う必要はないのではないか1。
Bundlerの作法に従うと、自分が使いたい開発支援系のgemとGemfileに登録されているgemが食い違っている場合には、Gemfileを編集してbundle installすることになる。この操作を複数のプロジェクトで繰り返すのは面倒だ。また、自分好みの設定は手元だけで使いたいこともあるだろう。GemfileやGemfile.lockをVCSで管理しているときには、誤って変更をコミットしないように気をつけなければならない。
ここでは主に、bundle exec --によるgemのバージョン固定の恩恵を受けながら、特定のgemだけはGemfileに登録せずに使う方法について解説する。
Bundler開発メンバーの見解
プロジェクト内で共有されるGemfileのほかに、個人的に使うgemを指定するGemfileが欲しいというissue(#183)が出されたことがある。多くの+1が集まったが、開発チームにはそのような複雑な機能を実装する余力はないとしてcloseされた。
解決方法
環境変数BUNDLE_GEMFILEを使う
ruby - How to use gems not in a Gemfile when working with bundler? - Stack Overflowの回答を参考にした。
次のようなファイルをGemfileと同じディレクトリに用意しておく。
# デフォルトのGemfileを読み込む
eval_gemfile "Gemfile"
# 自分が使いたいgemを宣言する
gem "pry-rescue"
gem "byebug"
BUNDLE_GEMFILEを使って、bundlerにGemfile.localをGemfileとして読み込ませる。
$ export BUNDLE_GEMFILE="Gemfile.local"
$ bundle install # Gemfile.local.lock が作られる(つまりGemfile.lockとは衝突しない)
$ set -u BUNDLE_GEMFILE bundle install # Gemfile.localを使いたくないときはこうする
Gemfile.localとGemfile.local.lockをcore.excludesfileや.git/info/excludeでgitの管理対象から除外すれば、リポジトリに自分用のGemfileやその痕跡が記録されることはない(参照: gitignore(5))。
デフォルトではBundlerはディレクトリを遡ってGemfileを探索してくれるが、BUNDLE_GEMFILEで指定するとFile.absolute_path(ENV['BUNDLE_GEMFILE'], Dir.pwd)に相当するパスしか見てくれないことに注意。
関連
いずれも動作確認はしていない。
-
Local gems in your Gemfile - Antonio's ramblings - コマンドの実行前に
Gemfile.lockがカレントディレクトリに存在するか確認して、BUNDLE_GEMFILEを適当に設定してくれる。zsh依存のシェルスクリプト。- デフォルトの
Gemfileを読み込ませたい場合は、Gemfile.localがないサブディレクトリでbundleを実行するか、env -u BUNDLE_GEMFILE bundle updateなどとすればよさそう。
- デフォルトの
- Gemfile tools
Gemfileから個人用のGemfileを読み込む
上記のスレッドではGemfileから個人用のGemfile.localを参照するという解決策も紹介されている。この方法だとGemfile.localがGemfile.lockに影響するので、Gemfile.lockをVCSで管理している場合には適さない。
tDiary, Redmine, fluentdなどで採用されている(参考: Gemfile を編集せずに任意の gem を追加して開発する方法 - Gemfile.local メソッド - sonots:blog)。
pry-debundle
Gemfileに指定されていないgemをrequireできるようにするpryのプラグイン。このプラグインのコードそのものを.pryrcに突っ込めばGemfileにpry-debundleを追加しなくても使える。
上記の方法と違って、使いたいgemをgem installするだけで済む。ただし、bundle execから起動するコマンドなど、pryのREPLを経由しないものは対象外。
git update-index --assume-unchanged
git update-index --assume-unchanged <files>でファイルが変更されていないことにできる。
自分が使うgemを追加するだけならこれでも問題ないが、コミットしたい変更もあるときにはあまり役に立たない。
$ git update-index --assume-unchanged Gemfile Gemfile.lock # 変更されていないことにする
$ git update-index --no-assume-unchanged Gemfile Gemfile.lock # 戻す
そのほか
-
Adan Alvarado : Use pry with Bundler without having it on your Gemfile - irb AlternativesをGemfileに登録せずに使う方法。
bundler execを使わずにpryなどを起動して、後からBundler.setupを使ってbundlerを有効にする。 -
Gemfile を編集せずに任意の gem を追加していじる2つの方法 - sonots:blog
- Gemfileを適当に書き換えたものを/tmpに置いて、それを
bundle --gemfile=...やBUNDLE_GEMFILEで参照する。 - 追加したいgemをrubyのsite_dirにインストールして、
RUBYOPTを使って$LOAD_PATHに追加する。
- Gemfileを適当に書き換えたものを/tmpに置いて、それを
関連