こんにちは。
今年は花粉影響が大きく、外出するのが辛い小林です。
今回はRuby on Rails(以下、Rails)を使用するようになってから、ずっと気になっていたことが(たくさん)あるのですが、それが1つ解決しました!!
その喜びを伝えたく、キーボードを執りました。
今回のテーマは、これです。
なぜ、bundlerでインストールしたgemをrequireせずに使用することができるのか?
はじめに
Rubyの勉強を始めたときにこういうことを覚えますよね?
外部ファイルを使用する場合は
requireにて対象のファイルをロードする
しかし、bundlerとRailsを組み合わせて使用している際に、requireを使用しませんよね?
なぜなのでしょうか?
なぜ、reuqireを省略することができるのか?
皆さんは、なぜだと思いますか?

実は、requireしなくても呼び出すことができる?

いいえ。
それだとrequireの存在意義がなくなってしまいます笑

「requireは同じファイルを複数回ロードしない」ということは、一度ロードされてしまえば、再度requireを実行する必要ない。
つまり、すでにどこかでrequireが実行されている?

よいところに目をつけましたね。
それでは、答え合わせをしていきましょう。
答え合わせ
答えは以下のファイルにあります。
config/application.rb
config/apprlication.rb
このファイル内で以下の記述があります。
Bundler.require(*Rails.groups)
参考:yasslab/sample_apps/blob/main/6_0/ch14/config/application.rb#L7
この処理によってGemfileに記載されているgemが依存関係を含めてロードすることができるようになります。
If you have a lot of dependencies, you might want to say “require all of the gems in myGemfile“. To do this, put the following code immediately followingrequire 'bundler/setup':Bundler.require(:default)参考:How to use Bundler with Ruby#Setting Up Your Application to Use Bundler
ソースコード的な解説をしだすと切りがないので省略しますが、興味がある方は以下を参考にしてください。
参考:bundler/lib/bunder.rb
Bundler.requireでGemfile内のgemをロードするのはわかったのですが、そもそもBundler自体もgemなので、どこかでrequireしないといけないのでは?
上記に記載がある通り、require 'bundler/setup'の後に実施するように記載されています。
該当コードを確認すると内部でBundlerをロードしています。
参考:bundler/lib/bundler/setup.rb
最後の疑問です。
config/application.rb内では、require 'bundler/setup'を実施していないではないですか。
config/boot.rb
config/application.rb内でrequire_relative 'boot'を実施しています。
config/boot.rbを確認すると、require 'bundler/setup'を実施していることが確認できます。
参考:yasslab / sample_apps sample_apps/6_0_0/ch14/config/boot.rb
注意事項
以下のように:require => falseと指定すると、Bundler.requireを実行しても、ロードされないので、注意してください。
Specify :require => false to prevent bundler from requiring the gem, but still install it and maintain dependencies.
gem 'rspec', :require => false gem 'sqlite3'参考:Gemfiles
最後に
最初のRails案件でプルリクエスト出した際に、「個別のrequireは不要」と指摘されて依頼、ずっと気にかけていたことなので、本当によかったです。
完全に理解しました。(Railsガイドちゃんと読まないと。。。)
他にも気になっているものは多々あるので、引き続き調査していこうと思います。

