Rubyのgemのコードリーディングをする時の備忘録

rubyのgemのコードリーディングをする時によく利用したことを　備忘録としてメモ。
（随時更新する。）

※rubyのバージョンは3.1.0

## gemのファイルの場所を知りたい時

`$LOAD_PATH.grep(/serach_word/)`で検索できる。

例）devise関連のgemの場所を知りたい場合

```
rails c
irb(main):010:0> $LOAD_PATH.grep(/devise/)
=> 
["YOUR_PATH/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/devise-4.8.1/lib",
 "YOUR_PATH/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/devise-4.8.1/app/controllers",
 "YOUR_PATH/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/devise-4.8.1/app/helpers",
 "YOUR_PATH/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/devise-4.8.1/app/mailers"]
```

## デバッグ

参考

https://docs.ruby-lang.org/ja/latest/library/debug.html

### ブレイクポイント

コード内に`binding.break`を書けば止まる

例

```:generators/devise/install_generator.rb
[12, 21] in ~/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/devise-4.8.1/lib/generators/devise/install_generator.rb
    12|
    13|       desc "Creates a Devise initializer and copy locale files to your application."
    14|       class_option :orm, required: true
    15|
    16|       def copy_initializer
=>  17|         binding.break
    18|         unless options[:orm]
    19|           raise MissingORMError, <<-ERROR.strip_heredoc
    20|           An ORM must be set to install Devise in your application.
    21|
=>#0    Devise::Generators::InstallGenerator#copy_initializer at ~/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/devise-4.8.1/lib/generators/devise/install_generator.rb:17
  #1    Thor::Command#run(instance=#<Devise::Generators::InstallGenerator:0..., args=[]) at ~/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/thor-1.1.0/lib/thor/command.rb:27
  # and 21 frames (use `bt' command for all frames)
(rdbg) 
```

参考

https://github.com/ruby/debug#invoke-with-the-debugger


### バックトレース(backtrace)

ブレイクポイントで止まった状態で`backtrace`を入力する


出力例

```:generators/devise/install_generator.rb
(rdbg) backtrace    
=>#0    Devise::Generators::InstallGenerator#copy_initializer at ~/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/devise-4.8.1/lib/generators/devise/install_generator.rb:17
  #1    Thor::Command#run(instance=#<Devise::Generators::InstallGenerator:0..., args=[]) at ~/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/thor-1.1.0/lib/thor/command.rb:27
  #2    Thor::Invocation#invoke_command(command=#<struct Thor::Command name="copy_initia..., args=[]) at ~/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/thor-1.1.0/lib/thor/invocation.rb:127
  #3    block {|_="copy_initializer", command=#<struct Thor::Command name="copy_initia...|} in invoke_all at ~/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/thor-1.1.0/lib/thor/invocation.rb:134
  #4    [C] Hash#each at ~/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/thor-1.1.0/lib/thor/invocation.rb:134
  #5    [C] Enumerable#map at ~/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/thor-1.1.0/lib/thor/invocation.rb:134
  #6    Thor::Invocation#invoke_all at ~/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/thor-1.1.0/lib/thor/invocation.rb:134
  #7    #<Class:Thor::Group>#dispatch(command=nil, given_args=[], given_opts=nil, config={:behavior=>:invoke, :destination_root=>...) at ~/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/thor-1.1.0/lib/thor/group.rb:232
  #8    Thor::Base::ClassMethods#start(given_args=[], config={:behavior=>:invoke, :destination_root=>...) at ~/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/thor-1.1.0/lib/thor/base.rb:485
  #9    Rails::Generators.invoke(namespace="devise:install", args=[], config={:behavior=>:invoke, :destination_root=>...) at ~/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/bundler/gems/rails-958af5235874/railties/lib/rails/generators.rb:263
  #10   Rails::Command::GenerateCommand#generate(#arg_rest=nil) at ~/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/bundler/gems/rails-958af5235874/railties/lib/rails/commands/generate/generate_command.rb:26
  #11   Thor::Command#run(instance=#<Rails::Command::GenerateCommand:0x0000..., args=["devise:install"]) at ~/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/thor-1.1.0/lib/thor/command.rb:27
  #12   Thor::Invocation#invoke_command(command=#<struct Thor::Command name="generate", ..., args=[["devise:install"]]) at ~/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/thor-1.1.0/lib/thor/invocation.rb:127
  #13   #<Class:Thor>#dispatch(meth="generate", given_args=["devise:install"], given_opts=nil, config={:current_command=>#<struct Thor::Comman...) at ~/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/thor-1.1.0/lib/thor.rb:392
  #14   #<Class:Rails::Command::Base>#perform(command="generate", args=[], config={:current_command=>#<struct Thor::Comman...) at ~/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/bundler/gems/rails-958af5235874/railties/lib/rails/command/base.rb:87
  #15   Rails::Command.invoke(full_namespace="generate", args=[], config={:current_command=>#<struct Thor::Comman...) at ~/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/bundler/gems/rails-958af5235874/railties/lib/rails/command.rb:48
  #16   <main> at ~/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/bundler/gems/rails-958af5235874/railties/lib/rails/commands.rb:18
  #17   [C] Kernel#require at ~/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/bootsnap-1.9.3/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23
  #18   block in require_with_bootsnap_lfi at ~/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/bootsnap-1.9.3/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23
  #19   Bootsnap::LoadPathCache::LoadedFeaturesIndex#register(short="rails/commands", long="/Users/k.nakama/.rbenv/versions/3.1.0/l...) at ~/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/bootsnap-1.9.3/lib/bootsnap/load_path_cache/loaded_features_index.rb:100
  #20   Kernel#require_with_bootsnap_lfi(path="rails/commands", resolved="/Users/k.nakama/.rbenv/versions/3.1.0/l...) at ~/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/bootsnap-1.9.3/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22
  #21   Kernel#require(path="rails/commands") at ~/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0/gems/bootsnap-1.9.3/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31
  #22   <main> at bin/rails:5
(rdbg)
```

## ステップオーバー(next)

ブレイクポイントで止まった状態で`n`もしくは`next`を入力する。
メソッド内部には入らない。


## ステップイン(step)

ブレイクポイントで止まった状態で`step`を入力する
メソッド内部に入る。

## ウォッチャ(display)

ブレイクポイントで止まった状態で`display 確認したい変数orクラスなど`を入力する
`undisplay`で登録したdisplayをすべて解除。
`undisplay 番号`で指定番号のdisplay解除

## gemのコードを修正したのを元に戻す

```
bundle pristine
```

参考

https://tech.basicinc.jp/articles/187