Gemfileにないgemを使いたい

アプリケーション本体や自動テストを実行するのに必要なgemは、開発者全員が同じものをインストールするべきだ。しかし、pry-*などの開発支援系のgemについては、開発者全員が同じものを使う必要はないのではないか[^needless-gems-in-dev]。

[^needless-gems-in-dev]: [Railsのdevelopmentにあっても微妙じゃね？って思うGemたち - 良いあそなすちゃん](http://asonas.hatenablog.com/entry/2014/07/25/110141)

Bundlerの作法に従うと、自分が使いたい開発支援系のgemとGemfileに登録されているgemが食い違っている場合には、Gemfileを編集して`bundle install`することになる。この操作を複数のプロジェクトで繰り返すのは面倒だ。また、自分好みの設定は手元だけで使いたいこともあるだろう。GemfileやGemfile.lockをVCSで管理しているときには、誤って変更をコミットしないように気をつけなければならない。

ここでは主に、`bundle exec --`によるgemのバージョン固定の恩恵を受けながら、特定のgemだけはGemfileに登録せずに使う方法について解説する。

## Bundler開発メンバーの見解

プロジェクト内で共有されるGemfileのほかに、個人的に使うgemを指定するGemfileが欲しいというissue([#183](https://github.com/bundler/bundler/issues/183))が出されたことがある。多くの+1が集まったが、開発チームにはそのような複雑な機能を実装する余力はないとしてcloseされた。

## 解決方法
### 環境変数`BUNDLE_GEMFILE`を使う

[ruby - How to use gems not in a Gemfile when working with bundler? - Stack Overflow](http://stackoverflow.com/questions/12237055/how-to-use-gems-not-in-a-gemfile-when-working-with-bundler)の[回答](http://stackoverflow.com/a/19941643/1614572)を参考にした。

次のようなファイルを`Gemfile`と同じディレクトリに用意しておく。

```Gemfile.local
# デフォルトのGemfileを読み込む
eval_gemfile "Gemfile"

# 自分が使いたいgemを宣言する
gem "pry-rescue"
gem "byebug"
```

`BUNDLE_GEMFILE`を使って、bundlerに`Gemfile.local`をGemfileとして読み込ませる。

```console
$ 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)](https://www.kernel.org/pub/software/scm/git/docs/gitignore.html)）。

デフォルトではBundlerはディレクトリを遡って`Gemfile`を探索してくれるが、`BUNDLE_GEMFILE`で指定すると`File.absolute_path(ENV['BUNDLE_GEMFILE'], Dir.pwd)`に相当するパスしか見てくれないことに注意。

#### 関連

いずれも動作確認はしていない。

* [Local gems in your Gemfile - Antonio's ramblings](http://blog.santosvelasco.com/2012/10/28/local-gems-in-your-gemfile/) - コマンドの実行前に`Gemfile.lock`がカレントディレクトリに存在するか確認して、`BUNDLE_GEMFILE`を適当に設定してくれる。zsh依存のシェルスクリプト。
  * デフォルトの`Gemfile`を読み込ませたい場合は、`Gemfile.local`がないサブディレクトリで`bundle`を実行するか、`env -u BUNDLE_GEMFILE bundle update`などとすればよさそう。
* [Gemfile tools](https://gist.github.com/terlar/3689896)

### `Gemfile`から個人用のGemfileを読み込む

上記のスレッドでは[`Gemfile`から個人用の`Gemfile.local`を参照する](http://stackoverflow.com/a/12237420/1614572)という解決策も紹介されている。この方法だと`Gemfile.local`が`Gemfile.lock`に影響するので、`Gemfile.lock`をVCSで管理している場合には適さない。

tDiary, Redmine, fluentdなどで採用されている（参考: [Gemfile を編集せずに任意の gem を追加して開発する方法 - Gemfile.local メソッド - sonots:blog](http://blog.livedoor.jp/sonots/archives/42259221.html)）。

### [pry-debundle](https://github.com/ConradIrwin/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を追加するだけならこれでも問題ないが、コミットしたい変更もあるときにはあまり役に立たない。

```console
$ 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](https://coderwall.com/p/drdcuq) - [irb Alternatives](https://www.ruby-toolbox.com/categories/irb_Alternatives)をGemfileに登録せずに使う方法。`bundler exec`を使わずにpryなどを起動して、後から`Bundler.setup`を使ってbundlerを有効にする。
* [Gemfile を編集せずに任意の gem を追加していじる２つの方法 - sonots:blog](http://blog.livedoor.jp/sonots/archives/38358846.html)
  1. Gemfileを適当に書き換えたものを/tmpに置いて、それを`bundle --gemfile=...`や`BUNDLE_GEMFILE`で参照する。
  2. 追加したいgemをrubyのsite_dirにインストールして、`RUBYOPT`を使って`$LOAD_PATH`に追加する。

## 関連

* [BundlerでGemfileを変更せずにローカルの:pathのgemを使う - Qiita](http://qiita.com/quattro_4/items/8ec707d527d64e109ee0)


---

<a rel="license" href="http://creativecommons.org/publicdomain/zero/1.0/">
  <img src="http://i.creativecommons.org/p/zero/1.0/80x15.png" style="border-style: none;" alt="CC0" />
</a>