Bundlerのconfigを見直す

昔Qiitaにこういう記事書いたんすよ

qiita.com

で、--pathは結構使ってたんだけど、最近のBundler(2.1.2)でこういう警告が出るようになった。

$ bundle --path vendor/bundle
[DEPRECATED] 
The `--path` flag is deprecated because it relies on being remembered across bundler invocations, 
which bundler will no longer do in future versions. Instead please use `bundle config set path 'vendor/bundle'`, 
and stop using this flag

要するに--pathで与えるんじゃなくて、bundle configでいい感じにセットするようにしなさいとのこと。 正直あんまりconfigファイル真面目に見てなかったし、いい機会なので公式ドキュメント読み直すことにした。

precondition

  • MacOS 10.14.5
  • Bundler version 2.1.2
  • ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-darwin18]

bundle config

bundler.io

$ bundle configコマンドは、設定のget/setや現在の設定情報を表示する機能などを提供してくれる。 割と$ git configコマンドに近い設計になっていると思う。

config file order

Bundlerのconfigファイルには設定の優先度が決まっており、以下の優先順位で適用される。

  1. ローカルのconfig(app/.bundle/config)
  2. 環境変数の設定値
  3. グローバルのconfig(~/.bundle/config)
  4. Bundlerの初期値

2の環境変数の設定値というのはどういうものか想像がしにくいかもしれない。 まずは、以下のように設定されている状況を作って、実際にどのような設定が反映されているか確認してみる。

#app.bundle/config
---
BUNDLE_PATH: "vendor/bundle"
BUNDLE_WITHOUT: "extra"
#~/.bundle/config
---
BUNDLE_PATH: "~/vendor/bundle"
BUNDLE_WITHOUT: "production"
$ echo $BUNDLE_PATH
hoge/fuga

この状態で、現在のコンテキストでのBundlerの設定値を表示するコマンド$ bundle config listを実行してみると、以下のような結果が得られる。

$ bundle config list
Settings are listed in order of priority. The top value will be used.
path
Set for your local app (/Users/username/ghq/github.com/rack/rack/.bundle/config): "vendor/bundle"
Set via BUNDLE_PATH: "hoge/fuga"
Set for the current user (/Users/username/.bundle/config): "~/vendor/bundle"

without
Set for your local app (/Users/username/ghq/github.com/rack/rack/.bundle/config): [:extra]
Set for the current user (/Users/username/.bundle/config): [:production]

後述するが、pathwithoutなどの設定値が表示される。Settings are listed in order of priority. The top value will be used.と書かれている通り、各設定値の一番上に表示されたものが利用される。

先ほどの環境変数の設定値は、BUNDLE_PATH="hoge/fuga"などと、configファイルと同じ変数名で値を格納しておくと、Bundlerの設定として認識されてロードされる。

Remembering Options

Bundlerには、bundle config setコマンドでconfigファイルに保存できるオプションがある。

bin

Ruby Gemには実行可能なファイルが含まれているものがいくつかある。例えば、Railsアプリを初期化したときはbin/railsというファイルが配置される。このファイルは実行可能で、$bin/rails sで実行できる。 この設定値に記述されたディレクトリに、実行可能なファイルたちが配置される。

path

$ bundle installでインストールするRuby Gemを、この設定値に記述されたディレクトリに配置する。 冒頭で推奨されていた設定方法がこれ。

$ bundle config set path vendor/bundle
Your application has set path to "vendor/bundle". This will override the global value you are currently setting

deployment

開発時には使用しないので、あまりお目に掛かることはないかもしれない。 このオプションを端的に説明すると、Gemfile.lockに書かれている通りにGemをインストールし、Gemfileに新しいGemを追記することができなくなる。名前の通り、本番環境にデプロイするときにGemのバージョンを固定するために使うものらしい。

詳しくはこちらの記事を参照すると良い。

bundler.io

with

Gemfileにはgroupという概念があり、withには、どのgroupをインストールの対象にするかを記述できる。

without

withの逆で、どのgruopをインストールの対象外にするかを記述できる。

他にもたくさんある

bundler.io

流石に多すぎるのでここでは割愛。

それ以外のBundlerの便利機能

ここから先は、configではないけどドキュメント読んでて見つけたBundlerの便利な機能をいくつかリストアップする。

bundle outdated

ローカルのGemfileで管理されているRuby Gemのバージョンが古いかどうかをチェックして、表示してくれる。

例えばRailsプロジェクトに適用してみるとこんな感じ。最新でないGemが全てリストアップされるので、プロジェクトの健全性を表す指標の1つになるかもしれない。

$ bundle outdated

Resolving dependencies....

Outdated gems included in the bundle:
  * actioncable (newest 6.0.2.1, installed 6.0.1)
  * actionmailbox (newest 6.0.2.1, installed 6.0.1)
  * actionmailer (newest 6.0.2.1, installed 6.0.1)
  * actionpack (newest 6.0.2.1, installed 6.0.1)
  * actiontext (newest 6.0.2.1, installed 6.0.1)
  * actionview (newest 6.0.2.1, installed 6.0.1)
  * activejob (newest 6.0.2.1, installed 6.0.1)
  * activemodel (newest 6.0.2.1, installed 6.0.1)
  * activerecord (newest 6.0.2.1, installed 6.0.1)
  * activestorage (newest 6.0.2.1, installed 6.0.1)
  * activesupport (newest 6.0.2.1, installed 6.0.1)
  * builder (newest 3.2.4, installed 3.2.3)
  * capybara (newest 3.30.0, installed 3.29.0) in groups "test"
  * doorkeeper (newest 5.2.3, installed 5.2.2) in groups "default"
  * ffi (newest 1.11.3, installed 1.11.1)
  * i18n (newest 1.8.1, installed 1.7.0)
  * listen (newest 3.2.1, installed 3.1.5, requested >= 3.0.5, < 3.2) in groups "development"
  * loofah (newest 2.4.0, installed 2.3.1)
  * minitest (newest 5.14.0, installed 5.13.0)
  * nokogiri (newest 1.10.7, installed 1.10.5)
  * public_suffix (newest 4.0.3, installed 4.0.1)
  * puma (newest 4.3.1, installed 3.12.1, requested ~> 3.11) in groups "default"
  * rack (newest 2.1.1, installed 2.0.7)
  * rails (newest 6.0.2.1, installed 6.0.1, requested ~> 6.0.0) in groups "default"
  * railties (newest 6.0.2.1, installed 6.0.1)
  * rake (newest 13.0.1, installed 13.0.0)
  * rb-inotify (newest 0.10.1, installed 0.10.0)
  * sass-rails (newest 6.0.0, installed 5.1.0, requested ~> 5) in groups "default"
  * selenium-webdriver (newest 3.142.7, installed 3.142.6) in groups "test"
  * sprockets (newest 4.0.0, installed 3.7.2)
  * sqlite3 (newest 1.4.2, installed 1.4.1, requested ~> 1.4) in groups "default"
  * thor (newest 1.0.1, installed 0.20.3)
  * tzinfo (newest 2.0.1, installed 1.2.5)
  * webdrivers (newest 4.2.0, installed 4.1.3) in groups "test"
  * webpacker (newest 4.2.2, installed 4.0.7, requested ~> 4.0) in groups "default"
  * zeitwerk (newest 2.2.2, installed 2.2.1)

bundle viz

Graphvizと連携して、Gemの依存性を画像で出力できる。 Railsプロジェクトで試してみたけど、デカすぎて使い物にならなかった...。

f:id:osamtimizer:20200113025109p:plain
Graphvizで出力されたRailsプロジェクトの依存性

そこそこの規模のRuby Gemであれば、割といい感じに出た。*1

f:id:osamtimizer:20200113025743p:plain
Ruby Gem(slack-ruby-bot)のプロジェクト

bundle open

bundle open [GEM]で、インストールされているGemのディレクトリをエディタで開くことができる。

開くためには、環境変数EDITORBUNDLE_EDITORにエディタの名前(vimとか)が記述されている必要がある。

Railsアプリ書いていて、Gem側で起きているエラーの原因がどちらにあるのかを調べるときに、Gem側にbinding.irbとかを記述する場合に役に立つと思う。

おわりに

ツール系の公式ドキュメントは読むたびに新しい発見があって結構楽しいので、暇な時に読むのがマイブームになりつつある。

*1:オススメといって書いておきながら、自分では使わないかも