BundlerでGemfileを変更せずにローカルの:pathのgemを使う

  • 71
    いいね
  • 1
    コメント
この記事は最終更新日から1年以上が経過しています。

Railsプロジェクトでgemを変更しながら開発する場合、

  • Gemfileに:pathでローカルのgemを指定 gem 'mygem', :path => '../mygem'
  • gemを変更したらgem側をプッシュ
  • 本体のプロジェクトのGemfileのgemの指定をリモート向けに戻してbundle update mygem
  • やっと本体のプロジェクトをコミット、プッシュ
  • またGemfileに:pathでローカルのgemを指定

することになりますが、頻度が多いと面倒になります。

bundle local

以下のコマンドにより、Gemfileを変更する必要がなくなります。

$ bundle config local.mygem ../mygem
($ bundle config local.mygem /Users/user/path/to/mygem)

設定はプロジェクトごとではなく、グローバルになるようです。

$ cat ~/.bundle/config
---
BUNDLE_LOCAL__MYGEM: ../mygem

bundle実行時の出力は少し違うので、設定の違いを判断できます。

$ bundle
Using mygem (0.1.9) from git@github.com:hoge/mygem.git (at ../mygem)

gem側のブランチを複数扱ったりする場合や、古いリビジョンを参照したいなどの場合には、bundleコマンドの挙動やGemfile.lockの変化などが、自分の意図に反して混乱する可能性もあります。
その場合はおとなしく元に戻して、従来通り:pathを使う事をお勧めします。
~/.bundle/configを消せば大丈夫なはずです。

Bundler 1.2から使えるようです。

その他、プロジェクトごとに指定できるかは未調査。

bundle local解除用alias

切り替えがしやすいように以下のようなaliasをおすすめ

alias bl_on='mv $HOME/.bundle_OFF $HOME/.bundle'
alias bl_off='mv $HOME/.bundle $HOME/.bundle_OFF'

次に述べる副作用の関係上、特にリリースなどに携わる人は良く理解して切り替えがすぐにできるようにしていることが望まれる

副作用

ローカルgemのプッシュし忘れ

考えられる副作用としては、gemをプッシュし忘れて、でもそれを参照する本体のプロジェクトは最新の状態でプッシュしたりしたときに、他のメンバーにとっては最新のgemが無く、プル+bundleするのに失敗するということが起こり得ると思います。

ローカルgemからのdependencyの追加

これはとても大切

特にリリース回りを担当する人は知っておかないと、リリース直前でなぜか起動できないとかいろいろ起こり得る

ローカルgem内の mygem.gemspecs.add_dependency 'some_shared_gem' を追加したとする。

ローカルgemを含むプロジェクト側をただbundle installしても、このdependencyは追加されない。何が問題となるかと言うと、ほとんどの場合追加されたdependencyはコード内でrequire 'some_shared_gem'を必要とする。プロジェクト側でrailsでもrakeでも起動しようとすると、some_shared_gemのLoad Errorになる。

対応方法は2つ

  • bundle localを解除して、gem側もプッシュ済みの状態で作業をすすめる
  • プロジェクト側でbundle update mygemする

bundle updateした後も、意図しない他のdependencyのgemがアップグレードされないように注意もしないといけない。最近だとjquery-railsは2.1.4と2.2系でjQuery自体のアップグレードになりプロジェクトが壊れる可能性がある)

その他

余談で、Rails界隈のすごい人たちが長い間議論してきて、いろいろなアプローチ、提案があったことをIssueから見て取れて面白いFeatureだと感じた。

Issue1Issue2Issue3 他