動機
今日とある方(エンジニア歴約1ヶ月)とメンタリングをしていて、bundle install --path vendor/bundle
がなんのためにあるのかとか、bundle list
とgem list
はどう違うのかなどが話題に上ったのでまとめようと思いました。
背景知識
最低限、bundlerを自身で使ったことがある方を想定して書かれています。
本編
bundle install --path vendor/bundle
について
結論
結論を先に言うと、--path
オプションをつけるのは開発時においては必要ありませんが、異なるバージョンのgemが混ざるのが嫌な人はつけましょう。
目的
--path
オプションをつける目的としては、プロジェクト下のディレクトリ(例えばvendor/bundle
)にgemをインストールすることで、グローバルにインストールされたgemとbundlerが管理するgemを分離することが挙げられます。他にも、ctagsなどを利用する際にgemがプロジェクト下にインストールされていると便利である可能性があります。
背景
このvendor/bundle
ですが、由来は--deployment
オプションにあるようです。
https://bundler.io/v2.0/man/bundle-install.1.html#DEPLOYMENT-MODE に記載されているように、bundle install --deployment
でインストールを実行した場合、--path
の指定がないならvendor/bundle
にgemがインストールされます。
これを開発環境で模倣するのが先述の--path vendor/bundle
の由来ということになりそうです。
問題点
bundle install --path vendor bundle
は利点もありますが欠点もあります。
特に重大なのは、同じようなアプリケーション(特にRailsアプリケーション)を何個も並行して開発する場合に、同一のgemを各アプリケーション下に重複してインストールすることになってしまい、ディスク容量を圧迫する恐れがあるという点です。
bundle install
のみでインストールを行う場合、グローバルにgemがインストールされ、以後はそちらのgemを単に参照するだけになるため、ディスク容量の面では効率的になります。
bundle list
とgem list
の違いについて
bundle list
bundle list
コマンドは、「あるプロジェクトがbundlerによって管理されている場合に、そこで使用されているgemを一覧表示するコマンド」です。
ここで重要なのは、bundle install
コマンドにどんなオプションを渡していても、ここで表示される内容は変わらないということです。
もちろん、そもそもbundlerを使っていない場合はこのコマンドは単にエラーになります。言い換えると、どのプロジェクトにいるか(ワーキングディレクトリがどこか)によって結果が変わります。
gem list
gem list
コマンドは、「グローバルにインストールされたgemを一覧表示するコマンド」です。
このコマンドはグローバルなコマンドなので、ワーキングディレクトリがどこであろうと結果は同じです。一方、bundle install --path vendor/bundle
などでインストールされたgemについては表示されません。
両コマンドの違いと使い分け
違いは上に書いた通りですが、使い分けとしては、基本的にRailsアプリケーションの開発においてはbundle list
コマンドを使用することが多いと思われます。
一方、例えばtmuxinatorやforemanのようなコマンド利用が主目的のgemをインストールしているケースにおいてはgem list
を使うことも多いでしょう。これは単純にgemが今の環境にインストールかどうかを調べる一つの有力な方法がgem list | grep 'GEM_NAME'
であるということによります。
Rubyのバージョンについての余談
上に書いてある「グローバル」という単語は厳密には「あるRubyのバージョンについて」という但し書きが必要になります。
現代のRuby開発環境においては、rbenv
やchruby
を使って複数のRubyをインストールするのは珍しくありません。この場合、使用するRubyのバージョンをスイッチするとインストールされているgemについても変更されます。換言すると、gem list
の結果はRubyのバージョンによって異なる可能性があります(bundle list
の結果については、どのRubyバージョンであってもbundle install
を実行してさえいれば結果は同じになります)。
また、現状複数のRubyに同じgemを同時にインストールする方法は特に用意されていないと思われます。一応、rbenv-default-gemsというものはありますが、事前に決められたものしかインストールできないので融通性に欠けます。
さらに余談
rubygemsとbundlerは(かなり先の話になりますが)統合される計画もあるという話を聞きました。興味深いですね!
終わりに
今回書いた内容に間違いがありましたら編集リクエストを送ってください!