crontabでrubyを実行するときに、Bundler.requireがエラーになる件の対応策



### この記事で書くこと
一つ前の記事で、cronでshell scriptをよび、rubyを実行するときに躓いたところについて書きましたが、
実はもう一つ躓いていたので、その内容を忘れないようにアウトプットします。
rubyファイルで `Bundler.require` するときに出たエラーについてです。

### 参考にさせていただいたサイト :bow: ありがとうございます。
- [crontabでRuby動かしたら private method `require’ called for Bundler:Module](http://shokai.org/blog/archives/6264)

### 結論

Gemfileが置いてあるディレクトリにcdで移動してからrubyを実行するようにすればいい。
でも、きちんと理解出来てない。

```sh:/home/user_name/ruby_test.sh
#!/bin/bash
cd /home/user_name/sample && ruby /home/user_name/sample/tasks/test_ruby.rb
```

### 起きたこと

#### 状況整理
```bash:crontab
00 13 * * * /bin/bash /home/user_name/ruby_test.sh > /home/user_name/log/ruby_test.log 2>&1
```


```sh:/home/user_name/ruby_test.sh
#!/bin/bash
export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"
rbenv shell 2.7.1
ruby /home/user_name/sample/tasks/test_ruby.rb
```

```rb:/home/user_name/sample/tasks/test_ruby.rb
require 'bundler/setup'
Bundler.require

# 以下rubyの処理が続きます
```

実行されたスクリプト。
ログファイルを見ると、何かエラーが。。


```tex:/home/user_name/log/ruby_test.log
/home/user_name/sample/tasks/test_ruby.rb:2:in `<main>': private method `require' called for Bundler:Module (NoMethodError)
```

上手く行ってないみたい。

でも、

```bash
cd /home/user_name/sample
ruby /tasks/test_ruby.rb
```

を実行すると、エラーが出ずに実行できるんです。

どうしてか解らなかったですが、

https://github.com/rubygems/bundler/blob/master/lib/bundler.rb#L173

`Bundler.require`
が何をしてるのかみてみることにしました。


```rb:bundler/lib/bundler.rb 

def require(*groups)
  setup(*groups).require(*groups)
end
```

`setup` がなんなのか追ってみます。

https://github.com/rubygems/bundler/blob/35be6d9a603084f719fec4f4028c18860def07f6/lib/bundler.rb#L139

```rb:bundler/lib/bundler.rb 

def setup(*groups)
   # Return if all groups are already loaded
   return @setup if defined?(@setup) && @setup 

   definition.validate_runtime!

   SharedHelpers.print_major_deprecations!
   if groups.empty?
     # Load all groups, but only once
     @setup = load.setup
   else
     load.setup(*groups)
   end
end
```

今回自分は引数なしで呼び出している為、
`@setup = load.setup` が呼ばれそうです。

```rb:bundler/lib/bundler.rb 
def load
  @load ||= Runtime.new(root, definition)
end
```

```rb:bundler/lib/bundler/runtime.rb
def setup(*groups)
   @definition.ensure_equivalent_gemfile_and_lockfile if Bundler.frozen_bundle?

   groups.map!(&:to_sym)

   # Has to happen first
   clean_load_path

   specs = groups.any? ? @definition.specs_for(groups) : requested_specs

   SharedHelpers.set_bundle_environment
   Bundler.rubygems.replace_entrypoints(specs)

   # Activate the specs
   load_paths = specs.map do |spec|
     unless spec.loaded_from
       raise GemNotFound, "#{spec.full_name} is missing. Run `bundle install` to get it."
     end

     check_for_activated_spec!(spec)

     Bundler.rubygems.mark_loaded(spec)
     spec.load_paths.reject {|path| $LOAD_PATH.include?(path) }
   end.reverse.flatten

   Bundler.rubygems.add_to_load_path(load_paths)

   setup_manpath

   lock(:preserve_unknown_sections => true)

   self
end
```

ここまで辿って、そもそもrequire呼べてないんだよ。先を見ても勉強になるだけだよ、と気づく。
private methodですってエラーには出てるけど、private methodに見えない。自分が見てる場所が間違ってるだけ？？？？？

注：今は[Bundler](https://github.com/rubygems/bundler/tree/master/lib/bundler)はarchiveになっています。
[rubygems](https://github.com/rubygems/rubygems)を使う方がいいようです。


時間があるときに、もう一度読んでみようと思いますが、
厳密にどこがエラーを返してるのか、どうしてエラーになったのか、まだ理解できてません。。 :disappointed: 

### とにかく、cdしたら動くことはわかったので、そのように書いてみて試す。

```sh:/home/user_name/ruby_test.sh
#!/bin/bash
export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"
rbenv shell 2.7.1

cd /home/user_name/sample && ruby /home/user_name/sample/tasks/test_ruby.rb
```

きちんと理解はできてないけど、一応動いた。。。 :thinking: 理解出来てないの気持ち悪い。週末の宿題。。
とりあえず調べ続けてみます。 :notebook: :runner: 

もし優しい方がいらっしゃったら、もし解ればコメントなどで教えていただけると嬉しいです。 :bow: 

読んでいただきありがとうございました。 :bow: