Bundler の bundler/setup と bundle exec
(=˘ ꒳ ˘=) Ruby のコードちんぷんかんぷんで読みづらい... import
やら require
やら load
やら色々読み込みの構文があるのに加えて、どのライブラリから来た定義なのかが追いづらかったり...
...という愚痴は置いておいて、Ruby のモジュールシステムを別の方面からややこしくしている Bundler の振る舞いについて整理したいと思います。ややこしいと書きましたが、プロジェクト下に依存ライブラリを置けるという、Node.js から来た身からすると勝手知ったるベンダリング手法が取れるありがたいツールです。
Bundler がインストールしたパッケージを使うためには bundle exec
したり require bundler/setup
したりと、いくつかお作法が必要そうなのですが、それぞれどう作用するかを実際に動かしながら整理していきます。
公式の記述は How to use Bundler with Ruby にあります。しかし情報がパラパラしていて追いづらかったので実際に試してみることにしたのでした。
試してみる
├── Gemfile ├── bin │ ├── with-bundler-setup.rb │ └── without-bundler-setup.rb ├── lib │ └── using-bundled-packages.rb └── vendor
というプロジェクトを用意します。 https://github.com/asa-taka/try-module-on-bundler に実際のファイルを置いておきました。
フロントのスクリプトをふた通り用意します。
# bin/with-bundler-setup.rb require 'rubygems' require 'bundler/setup' require './lib/using-bundled-packages'
# bin/without-bundler-setup.rb require './lib/using-bundled-packages'
孫 require
の振る舞いを見たかったので一段 lib/using-bundled-packages.rb
というスクリプトを挟んでいます。
# lib/using-bundled-packages.rb require 'awesome_print'
として awesome_print
を呼んでいます。vendor 下にインストールされた awesome_print
には print 'awesome_print by bundler loaded'
と仕込んで、Bundler によりインストールされたパッケージが実行された場合にテキストがプリントされるようにしました。
試した結果
bundle exec ruby ./bin/with-bundler-setup
のように各組み合わせを試したところ以下のような結果になりました。
実行コマンド | bundler/setup なし | bundler/setup あり |
---|---|---|
ruby .... |
global のパッケージ | Bundler によるパッケージ |
bundle exec ruby ... |
Bundler によるパッケージ | Bundler によるパッケージ |
つまり bundle exec
を使う、もしくはエントリポイントで require bundler/setup
をすると孫 require
でも Bundler によるパッケージが使われることになりますね。
毎回 bundle exec
するのも面倒なので require bundler/setup
の方が楽そうですね。
どういう処理でこうなっているのかはまた掘り下げてみたいところです。