やわらかテック

興味のあること。業務を通して得られた発見。個人的に試してみたことをアウトプットしています🍵

binding.irbでdebugコマンドが使えないのはirbのバージョンが古いため

僕はRubyで何かしら開発をする時にbinding.pryというデバッグツールを愛用してきました。
Rubyを書き始めたのが確か、2.3系の頃で当時からbinding.pryは非常に人気のデバッグツールでした。
しかし、Rubyのバージョンアップにつれてbinding.irbが標準gemとなりインストールをしなくても使用可能になったため、最近はbinding.irbを使うようになりました。

しかし、なぜかコード中にbinding.irbと挿入してIRBは立ち上がるものの、debugと入力してもエラーが表示され、デバッグ画面に遷移できませんでした。しかし、プライベートで使っているPCではdebugコマンドが使えており、この違いは何なんだろうか...と気になって調べてみました。

irbのバージョンが問題だった

binding.irbはirbというgemで管理されています。
最新のirbのコードを見てみると、実行可能なコマンドの一覧にdebugが定義されていることが分かります。

@EXTEND_COMMANDS = [
  :
  [
    :irb_debug, :Debug, "cmd/debug",
    [:debug, NO_OVERRIDE],
  ],
  :
]

ruby/extend-command.rb at master · ruby/ruby · GitHub

現時点(2023/05/24)では、最新のRubyバージョンは3.3.0で使用しているirbは1.6.4のようです。
標準gemなのでGemfileでの管理はされていないため、Rubyのバージョンによってirbは固定されていると考えた方が良いのいでしょうか。

debugコマンドが使えなかった業務PCで使っているRubyバージョンは3.1.2で、irbは1.4.1と少し古いようです。

irb(main):001:0> IRB.version
=> "irb 1.4.1 (2021-12-25)"
irb(main):002:0> RUBY_VERSION
=> "3.1.2

irb(main):004:0> debug
/Users/okabe/ruby/sample.rb:4:in `<main>': undefined local variable or method `debug' for main:Object (NameError)
  from <internal:prelude>:5:in `irb'
  from sample.rb:3:in `<main>'

ruby/NEWS.md at master · ruby/ruby · GitHub

irbが1.4.1時のコードを見ると、debugが実行可能なコマンド一覧に定義されていないことが分かりました。
(コードは手元の環境にダウンロードして確認しました)

@EXTEND_COMMANDS = [
  : # debugが定義されていない
]

Release v1.4.1 · ruby/irb · GitHub

つまりdebugコマンドが使えなかったのはirbのバージョンが古かったからなんですね。
irbがRubyの標準gemとなったことで、バージョンを全く意識していなかったので完全に盲点でした...。

irbバージョンの更新

ローカル環境の場合

ローカル環境にインストールされているirbはgem update irbで簡単にバージョンアップ出来ました。
Rubyのバージョン管理にはrbenvを使っています。

$ gem update irb
Updating installed gems
Updating irb
Fetching irb-1.6.4.gem
:
Gems updated: irb

$ gem list | grep irb
irb (1.6.4, default: 1.4.1)

irbのバージョンが1.3.5から1.6.4になったことで、ローカル環境ではdebugコマンドが使えるようになりました。
デバッグ画面に遷移したことでbinding.pryで使っていたnextcontinueなどのコマンドも使用可能になり、完全にbinding.irbへ移行することが出来ました。

ruby sample.rb
hello

From: sample.rb @ line 3 :

    1: puts "hello"
    2:
 => 3: binding.irb
    4:
    5: puts "nice"
    6:

irb(main):001:0> debug
[1, 6] in sample.rb
     1| puts "hello"
     2|
=>   3| binding.irb
     4|
     5| puts "nice"
     6|
=>#0    <main> at sample.rb:3
(rdbg) next    # command
[1, 6] in sample.rb
     1| puts "hello"
     2|
     3| binding.irb
     4|
=>   5| puts "nice"
     6|
=>#0    <main> at sample.rb:5

rbenvを使っている場合

新しくGemfileにirbを追加する必要がありました。
またdebugコマンドを使うにはdebugというgemも追加する必要があります。

gem 'irb'
gem 'debug'
$ bundle i
Fetching gem metadata from https://rubygems.org/.......
:
Using irb 1.6.4
Using debug 1.8.0
Bundled gems are installed into `./vendor/bundle`

これでdebugコマンドが使えることを確認しました。
ただせっかく標準gemになったので、Gemfileにirbとdebugを追加するのは何だかなぁ...という感じです。
大人しくRubyのバージョンアップをするのが良さそうです。

stackoverflow.com

少しでも「ええな〜」と思ったらイイネ!・シェア!・はてなブックマークを頂けると励みになります。

参考文献