RubyでrequireしたらLoadError (cannot load such file -- ruby_file)になった時に

# はじめに

なにも考えずに、ruby で `require` してますんで `LoadError (cannot load such file -- your_ruby_file_here)` となった時の話でも書こうと思います

# 今回のケース

Rubyのバージョン

```
$ ruby -v
ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-darwin19]
```

このようなフォルダ構成のケースです

```
$ tree
.
├── module.rb
└── sub_modules
    ├── sub_module_a.rb
    ├── sub_module_b.rb
    └── sub_module_c.rb
```

```ruby:module.rb 
require 'sub_modules/sub_module_a'
require 'sub_modules/sub_module_b'
require 'sub_modules/sub_module_c'

module MainModule
  Version = "2.3.0"
end
```

```ruby:sub_modules/sub_module_a.rb 
module SubModuleA
 Version = "1.0.0"
end
```

# `require`

この状況で`module.rb`をmainからロードしようとするとエラーになることがあります

```irb
irb(main):004:0> require 'module'
Traceback (most recent call last):
        7: from /Users/masaino/.rbenv/versions/2.7.1/bin/irb:23:in `<main>'
        6: from /Users/masaino/.rbenv/versions/2.7.1/bin/irb:23:in `load'
        5: from /Users/masaino/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/irb-1.2.3/exe/irb:11:in `<top (required)>'
        4: from (irb):3
        3: from (irb):4:in `rescue in irb_binding'
        2: from /Users/masaino/.rbenv/versions/2.7.1/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require'
        1: from /Users/masaino/.rbenv/versions/2.7.1/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require'
LoadError (cannot load such file -- module)
```

これは、`require`が参照している`$LOAD_PATH` にカレントディレクトリがはいっていないから`module.rb`がみつけられないということのようです。なので`./`をつけて以下のようにしてみます

```irb
irb(main):006:0> require './module'
Traceback (most recent call last):
       10: from /Users/masaino/.rbenv/versions/2.7.1/bin/irb:23:in `<main>'
        9: from /Users/masaino/.rbenv/versions/2.7.1/bin/irb:23:in `load'
        8: from /Users/masaino/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/irb-1.2.3/exe/irb:11:in `<top (required)>'
        7: from (irb):5
        6: from (irb):6:in `rescue in irb_binding'
        5: from /Users/masaino/.rbenv/versions/2.7.1/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require'
        4: from /Users/masaino/.rbenv/versions/2.7.1/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require'
        3: from /Users/masaino/load_path/module.rb:1:in `<top (required)>'
        2: from /Users/masaino/.rbenv/versions/2.7.1/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require'
        1: from /Users/masaino/.rbenv/versions/2.7.1/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require'
LoadError (cannot load such file -- sub_module_a)
```

エラーメッセージが`LoadError (cannot load such file -- sub_module_a)` に変わりました。`module`自体はロードできているが、今回のケースでは`module.rb`がさらに`sub_module`を`require`しているので、そこでこけているようです。

# `require_relative`

「現在のファイルからの相対パスで require する」ものとして`require_relative`もありますが、結果は同じです。

```irb
irb(main):005:0> require_relative 'module'
Traceback (most recent call last):
        9: from /Users/masaino/.rbenv/versions/2.7.1/bin/irb:23:in `<main>'
        8: from /Users/masaino/.rbenv/versions/2.7.1/bin/irb:23:in `load'
        7: from /Users/masaino/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/irb-1.2.3/exe/irb:11:in `<top (required)>'
        6: from (irb):4
        5: from (irb):5:in `rescue in irb_binding'
        4: from (irb):5:in `require_relative'
        3: from /Users/masaino/load_path/module.rb:1:in `<top (required)>'
        2: from /Users/masaino/.rbenv/versions/2.7.1/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require'
        1: from /Users/masaino/.rbenv/versions/2.7.1/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require'
LoadError (cannot load such file -- sub_module_a)
```

# `$LOAD_PATH`

ということで、素直に`$LOAD_PATH`にカレントディレクトリを設定した方が良さそうです。そもそも今の`$LOAD_PATH`はどうなってるんだ？

```irb
irb(main):001:0> puts $LOAD_PATH
/usr/local/Cellar/rbenv/1.1.2/rbenv.d/exec/gem-rehash
/Users/masaino/.rbenv/versions/2.7.1/lib/ruby/site_ruby/2.7.0
/Users/masaino/.rbenv/versions/2.7.1/lib/ruby/site_ruby/2.7.0/x86_64-darwin19
/Users/masaino/.rbenv/versions/2.7.1/lib/ruby/site_ruby
/Users/masaino/.rbenv/versions/2.7.1/lib/ruby/vendor_ruby/2.7.0
/Users/masaino/.rbenv/versions/2.7.1/lib/ruby/vendor_ruby/2.7.0/x86_64-darwin19
/Users/masaino/.rbenv/versions/2.7.1/lib/ruby/vendor_ruby
/Users/masaino/.rbenv/versions/2.7.1/lib/ruby/2.7.0
/Users/masaino/.rbenv/versions/2.7.1/lib/ruby/2.7.0/x86_64-darwin19
=> nil
```

確かにカレントディレクトリはないので追加してみます

```irb
irb(main):002:0> $LOAD_PATH.push('.')
=> ["/usr/local/Cellar/rbenv/1.1.2/rbenv.d/exec/gem-rehash", "/Users/masaino/.rbenv/versions/2.7.1/lib/ruby/site_ruby/2.7.0", "/Users/masaino/.rbenv/versions/2.7.1/lib/ruby/site_ruby/2.7.0/x86_64-darwin19", "/Users/masaino/.rbenv/versions/2.7.1/lib/ruby/site_ruby", "/Users/masaino/.rbenv/versions/2.7.1/lib/ruby/vendor_ruby/2.7.0", "/Users/masaino/.rbenv/versions/2.7.1/lib/ruby/vendor_ruby/2.7.0/x86_64-darwin19", "/Users/masaino/.rbenv/versions/2.7.1/lib/ruby/vendor_ruby", "/Users/masaino/.rbenv/versions/2.7.1/lib/ruby/2.7.0", "/Users/masaino/.rbenv/versions/2.7.1/lib/ruby/2.7.0/x86_64-darwin19", "."]
```

再度、ロードしてみると、いけました :thumbsup:

```irb
irb(main):006:0> require 'module'
=> true
irb(main):003:0> MainModule::Version
=> "2.3.0"
irb(main):004:0> SubModuleA::Version
=> "1.0.0"
```

# `RUBYLIB` を使う方法

`RUBYLIB` を export しておく方法でもいけます（指定したパスがサーチパスに追加される）

```
$ RUBYLIB=.
$ export RUBYLIB
```

# 参考にしたサイト

- [Rubyがライブラリをロードする際のパスを確認してみる](https://yk5656.hatenadiary.org/entry/20140806/1407855304)
- [`$LOAD_PATH`を設定する方法](https://littlebuddha.hatenadiary.org/entry/20081020/1224483302)