リモートプロセスのIrbセッションをローカルプロセスのRelineを使って操作できるirb-remoteというGemを作った

irb-remoteというGemを作ったので紹介します。

https://github.com/QWYNG/irb-remote

irb-remoteとは

irb-remoteは、リモートプロセスのIrbセッションをローカルプロセスのRelineを使って操作できるようにするGemです。 プロセス間通信にはdRubyを使用しています。

irb-remoteを作成した背景

green_dayというAtcoderのページをスクレイピングしてテストを書いてくれるGemを作ったのですが、IOをキャプチャするテストをする関係上、Binding#irbを使ってデバッグすることが厳しかったので、リモートプロセスのIrbを操作できる何かがあればいいなと思い作りました。

  it 'test with "2 900\n"' do
    # abc150/A.rb内でirbを起動してもIO
    io = IO.popen('ruby abc150/A.rb', 'w+')
    io.puts("2 900\n")
    io.close_write
    expect(io.readlines.join).to eq("Yes\n")
  end
 1) abc150/A.rb test with "2 900\n"
     Failure/Error: expect(io.readlines.join).to eq("Yes\n")

       expected: "Yes\n"
            got: "\nFrom: abc150/A.rb @ line 1 :\n\n => 1: binding.irb\n\nSwitch to inspect mode.\n2 900\n/home/qwyng/...0\e[m\n\e[1m  ^~~\e[m\n\n\tfrom <internal:prelude>:5:in `irb'\n\tfrom abc150/A.rb:1:in `<main>'\n\n"

       (compared using ==)

       # abc150/A.rb内でirbを起動すると、ただテストが失敗するだけでIrbを操作できない
       Diff:
       @@ -1,13 +1,25 @@
       -Yes
       +
       +From: abc150/A.rb @ line 1 :
       +
       + => 1: binding.irb
       +
       +Switch to inspect mode.
       +2 900
       +/home/qwyng/.rbenv/versions/3.2.2/lib/ruby/3.2.0/irb/workspace.rb:119:in `eval': /home/qwyng/green_day/abc150/A.rb:1: syntax error, unexpected integer literal, expecting end-of-input (SyntaxError)
       +2 900
       +  ^~~
       +
       +        from <internal:prelude>:5:in `irb'
       +        from abc150/A.rb:1:in `<main>'

     # ./abc150/spec/A_spec.rb:6:in `block (2 levels) in <top (required)>'

irb-remoteを使うと、リモートプロセスのIrbを操作できるので、上記のような問題を解決できます。

dRubyを使うという発想

dRubyを使ってリモートプロセスのIrbを操作するという発想は、pry-remoteirb_remoteでもうすでに試されていることでした。 どちらもRelineには対応しておらず、今回はRelineを使いたかったので別のGemを作りました。

この記事を書いた理由

勉強会でirb-remote的な話がなされいたっぽいので… 正直僕の実装はめちゃくちゃ実装なので、ちゃんとした人がちゃんと作ったらもっといいものができると思います。 irb-remoteという贅沢な名前を使ってしまったので、もしアレだったらすぐ名前変えます!!!すんません!!!