rubygemのインストール先と、requireでどのように呼び出して使っているかを調べた。
概要
rubygemを作って公開しよう!と意気込んでいろいろ情報を集め、さあ作るぞ!ってなったときに、ふと、
「いままでrailsプロジェクトでさんざん使ってきたけど…gemってどこにインストールされて、どういう仕組みで読み込んで使ってるんだ?」と疑問が湧いてきた。
なので調べた。
結論
bundle installでインストールされたgemは、$ gem environment
の出力結果のINSTALLATION DIRECTORY
に配置され、require
で組み込み変数$LOAD_PATH
内のパスを起点として検索され、呼び出され、使用できるようになっている。
gemのインストール先
bundle installでインストールされたgemは、$ gem environment
の出力結果のINSTALLATION DIRECTORY
に配置される。
$ gem environment RubyGems Environment: - RUBYGEMS VERSION: 3.2.3 - RUBY VERSION: 3.0.0 (2020-12-25 patchlevel 0) [x86_64-darwin19] - INSTALLATION DIRECTORY: /Users/horimotonaomichi/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0 - USER INSTALLATION DIRECTORY: /Users/horimotonaomichi/.gem/ruby/3.0.0 - RUBY EXECUTABLE: /Users/horimotonaomichi/.rbenv/versions/3.0.0/bin/ruby - GIT EXECUTABLE: /usr/local/bin/git - EXECUTABLE DIRECTORY: /Users/horimotonaomichi/.rbenv/versions/3.0.0/bin - SPEC CACHE DIRECTORY: /Users/horimotonaomichi/.gem/specs - SYSTEM CONFIGURATION DIRECTORY: /Users/horimotonaomichi/.rbenv/versions/3.0.0/etc - RUBYGEMS PLATFORMS: - ruby - x86_64-darwin-19 - GEM PATHS: - /Users/horimotonaomichi/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0 - /Users/horimotonaomichi/.gem/ruby/3.0.0 - GEM CONFIGURATION: - :update_sources => true - :verbose => true - :backtrace => false - :bulk_threshold => 1000 - REMOTE SOURCES: - https://rubygems.org/ - SHELL PATH: - /Users/horimotonaomichi/.rbenv/versions/3.0.0/bin - /usr/local/Cellar/rbenv/1.2.0/libexec - /Users/horimotonaomichi/.rbenv/shims - /Users/horimotonaomichi/.rbenv/bin - /Users/horimotonaomichi/.nodebrew/current/bin - /usr/local/bin - /usr/bin - /bin - /usr/sbin - /sbin
読み込みの仕組み
rubyのrequire
の読み込み対象は、rubyの組み込み変数$LOAD_PATH
内のパスを起点とし、相対パスでファイルを検索する。
検索の仕組みは単純で、
- $LOAD_PATH($:)を順に辿る
- 目的のファイルが見つかったら終了
- 最後まで来たらLoadError例外
$ ruby -e 'puts $LOAD_PATH'
とすると、$LOAD_PATH内に格納されているパスを見ることができる。
$ ruby -e 'puts $LOAD_PATH' /usr/local/Cellar/rbenv/1.2.0/rbenv.d/exec/gem-rehash /Users/horimotonaomichi/.rbenv/versions/3.0.0/lib/ruby/site_ruby/3.0.0 /Users/horimotonaomichi/.rbenv/versions/3.0.0/lib/ruby/site_ruby/3.0.0/x86_64-darwin19 /Users/horimotonaomichi/.rbenv/versions/3.0.0/lib/ruby/site_ruby /Users/horimotonaomichi/.rbenv/versions/3.0.0/lib/ruby/vendor_ruby/3.0.0 /Users/horimotonaomichi/.rbenv/versions/3.0.0/lib/ruby/vendor_ruby/3.0.0/x86_64-darwin19 /Users/horimotonaomichi/.rbenv/versions/3.0.0/lib/ruby/vendor_ruby /Users/horimotonaomichi/.rbenv/versions/3.0.0/lib/ruby/3.0.0 /Users/horimotonaomichi/.rbenv/versions/3.0.0/lib/ruby/3.0.0/x86_64-darwin19
疑問点
bundle install —path vendor/bundleでインストールした場合はどうなる?
プロジェクト内のvendor/bundleディレクトリにインストールされる。これをそのままrequireはできないので、プロジェクト内にインストールしたgemを読み込んで使用するためのBundler.require
メソッドがある。
ただし、Bundler 2.1 以降、 --path
オプションは deprecated(非推奨) となっており、基本的にはgemはグローバルにインストールして使うのが主流っぽい。
参考:
- https://qiita.com/jnchito/items/62adbea043abf72fa7cc
- https://qiita.com/jnchito/items/99b1dbea1767a5095d85
Railsの場合は?
Railsプロジェクトにおいても、bundle installのインストール先は$ gem environment
の出力結果のINSTALLATION DIRECTORY
。
railsではgemをrequireする必要はない。
理由はconfig/application.rb
にGemfile内のgemを一括で読み込む設定がなされているため。
参考:
- https://zenn.dev/toshi023/articles/d99b00510aafb3
- https://qiita.com/kaishuu0123/items/2a91495e7daa8c7783ed
感想
gemのインストール先を調べていくうちに、requireの仕様まで学ぶことができてよかった。
また、gemはグローバルにおいて使うのが主流ということもわかった。なんとなーく「グローバル汚染するのはよくないのかなあ?」と思っていたのがスッキリした。