Gemfileにないgemを使いたい

  • 89
    Like
  • 0
    Comment
More than 1 year has passed since last update.

アプリケーション本体や自動テストを実行するのに必要な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.local
# デフォルトの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.localGemfile.local.lockcore.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.localGemfile.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 # 戻す

そのほか

関連



CC0