Gem やファイルを読み込むために使う require
と require_relative
。違いは以下の点だけかと思ったら、そこまで単純でもないらしい。
この前自分で作ったこんなディレクトリがあったので、require
をどう書いたかを見てみる。
. ├── blog.rb └── blog_test.rb
require
blog_test.rb で、Minitest のライブラリと、blog.rb(自分で作ったファイル)を読み込んでいる部分。ファイル名の拡張子は省略できる。
require "minitest/autorun" require "./blog"
require "./blog"
の ./
を削除して require "blog"
にしてみたところ、LoadError
になった。
$ ruby blog_test.rb Traceback (most recent call last): 2: from blog_minitest.rb:2:in `<main>' 1: from /Users/masuyama/.rbenv/versions/2.7.0/lib/ruby/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require' /Users/masuyama/.rbenv/versions/2.7.0/lib/ruby/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require': cannot load such file -- blog (LoadError)
これは想定通りだけど、require "minitest/autorun"
って全然絶対パスじゃないじゃないか…。
リファレンスを見てみる。
require(feature) -> bool
Ruby ライブラリ feature をロードします。拡張子補完を行い、同じファイルの複数回ロードはしません。
feature が絶対パスのときは feature からロードします。 feature が相対パスのときは組み込み変数 $: に示されるパスを順番に探し、最初に見付かったファイルをロードします。このとき、$: の要素文字列の先頭文字が~
(チルダ) だと、環境変数 HOME の値に展開されます。また~USER
はそのユーザのホームディレクトリに展開されます。
Kernel.#require (Ruby 2.7.0 リファレンスマニュアル)
なるほど。相対パスで読み込めるパスは、以下で確認できる。これ以外の場所にあるファイルは、絶対パスで指定する必要があるということだ。
$ ruby -e 'puts $:' /usr/local/Cellar/rbenv/1.1.2/rbenv.d/exec/gem-rehash /Users/masuyama/.rbenv/versions/2.7.0/lib/ruby/site_ruby/2.7.0 /Users/masuyama/.rbenv/versions/2.7.0/lib/ruby/site_ruby/2.7.0/x86_64-darwin19 /Users/masuyama/.rbenv/versions/2.7.0/lib/ruby/site_ruby /Users/masuyama/.rbenv/versions/2.7.0/lib/ruby/vendor_ruby/2.7.0 /Users/masuyama/.rbenv/versions/2.7.0/lib/ruby/vendor_ruby/2.7.0/x86_64-darwin19 /Users/masuyama/.rbenv/versions/2.7.0/lib/ruby/vendor_ruby /Users/masuyama/.rbenv/versions/2.7.0/lib/ruby/2.7.0 /Users/masuyama/.rbenv/versions/2.7.0/lib/ruby/2.7.0/x86_64-darwin19
参考:requireとrequire_relativeの違いとは? - (゚∀゚)o彡 sasata299's blog
require_relative
現在のファイルからの相対パスで require します。
Kernel.#require_relative (Ruby 2.7.0 リファレンスマニュアル)
こちらのリファレンスは簡潔。
さっきの例を書き換えてみた。
require "minitest/autorun" require_relative "blog"
エラーは起きず、ちゃんと読み込めた。
ちなみに、正しくない書き方だと思うが、require_relative "./blog"
としても動く。
どっちを使うべきなのか
require_relative
は、require
より後からできたものだ。Ruby コミッターの znz さんのブログによると、以前はrequire
でカレントディレクトリのファイルも読み込むことができたが、脆弱性の元になるということでカレントディレクトリのファイルを直接読み込めなくして、require_relative
ができたそうだ。
明記はされていませんが require_relative が推奨されるようになったようです。
require './file'とrequire_relative 'file'の違い - @znz blog
require "./blog"
のような書き方は、脆弱性の原因になりうるとのこと。
ということで、Gem などを読み込むときはrequire
で、自分で作ったファイルなどを読み込むときはrequire_relative
を使うのがよさそう。知らなかった。