RubyKaigi 2026に参加してきました。現地参加はRubyKaigi 2015以来です。RubyKaigi本体も楽しかったのですが、関連イベントとして開催されたコード懇親会/Code Party(Social Coding) at RubyKaigi 2026もかなり楽しく、終電の差し迫るなか、勢い余ってruby/uriへのIssueを提出してしまったのでした。

会場に到着したらRubyをインストールする

RubyKaigiでの作業1が終わって会場の開始5分前くらいに会場の会議室に到着すると、多くの参加者がわいわい話をしながら軽食を食べていました。熱気。みなさんコード懇親会を楽しみにしている雰囲気です。やっぱりみんなコードを書くのだいすきよね。僕も軽食(とくにお寿司がおいしかった!)をいただいて、ラップトップを開いたところで、先日Rubyのリリースがあったのを思い出しました。

$ brew update ruby-build
$ rbenv install 4.0.3
$ cd ~c/src/local/rk26-code-party
$ rbenv local 4.0.3

dRubyでオブジェクトをやりとりする

僕が参加したのは、作者のsekiさんと一緒にdRubyを触ってみるグループで、用意していただいていた資料に沿ってdRubyを触ります。Ruby 3.0以降ではWEBrickは標準ライブラリではないので、gemとしてインストールします。最終的にGemfileは下記のようになりました。

source "https://rubygems.org"
gem "drb", "~> 2.2"
gem "webrick", "~> 1.9"
gem "irb", "~> 1.18"
gem "driq", "~> 0.4.3"

macOSは自分がIPv6に居ると思っている

dRubyでは一部のクラスのオブジェクトのやりとりにサーバが必要なので、ホストとポートを指定して起動するサーバとは別にクライアント側のプロセスでもサーバを起動します。

(サーバ)

$ bundle exec irb -r drb
> h = Hash.new
> DRb.start_service('druby://localhost:54000', h)
  :
 @exported_uri=["druby://localhost:54000"],
  :
   @config=
    {tcp_original_host: "localhost",
  :
     tcp_port: 54000},
  :

(クライアント)

$ bundle exec irb -r drb
> DRb.start_service
  :
 @exported_uri=["druby://::1:49357"],
  :
   @config=
    {tcp_original_host: "",
  :
     tcp_port: 49357},
> h = DRbObject.new_with_uri("druby://localhost:54000")
> h[:greeting] = "Hello, World!"

ここで、@exported_uridruby://::1:49357となっていることが気になりました。

IPv6アドレスのURI

RFC 2732によると、ホスト名部がIPv6であるURLではホスト名部を角かっこ[]で囲う必要があるようですが、上記で DRb.start_serviceが返したオブジェクトでは、@exported_uri::1が角かっこに囲まれていません。

ここでdRubyのコードを追ってみます。MacOS 15.7.5上のRuby 4.0.3のdRuby 2.2.3です。@exported_uriのホスト名部分は下記のメソッドで得ているようです。

(drb/drb.rb)

  :
    # Returns the hostname of this server
    def self.getservername
      host = Socket::gethostname
      begin
        Socket::getaddrinfo(host, nil,
                                  Socket::AF_UNSPEC,
                                  Socket::SOCK_STREAM,
                                  0,
                                  Socket::AI_PASSIVE)[0][3]
      rescue
        'localhost'
      end
    end
  :

irbで試してみると確かに::1になるようです。

URIにするコードは下記のようになっていました。たしかにdruby://::1:<ポート番号>となりそうです。

  :
      if ... 
        host = getservername
        soc = open_server_inaddr_any(host, port)
      else
  :
      end
      port = soc.addr[1] ...
  :
      uri = "druby://#{host}:#{port}"
  :

このインスタンス変数はdRubyが動作する際に参照されることはなさそうだけれど、なんとなく気持ち悪いのでurl標準ライブラリなどでRFCどおりに整形してもらえばいいだろう。

標準ライブラリでURLを整形してもらう

$ irb

⢀⡴⠊⢉⡟⢿  IRB v1.18.0 - Ruby 4.0.3
⣎⣀⣴⡋⡟⣻  Type "help" for commands, "help <cmd>" for details
⣟⣼⣱⣽⣟⣾  ~/c/src/local/rk26-code-party

> require 'uri'
> s = URI::Generic.new('https', nil, '::1', 443, nil, '/', nil, nil, nil).to_s
=> "https://::1:443/"

ありゃ。角かっこで囲まれていない。パースはできるのかな?

> URI.parse(s)
.../4.0.3/lib/ruby/4.0.0/uri/rfc3986_parser.rb:130:in 'URI::RFC3986_Parser#split': bad URI (is not URI?): "https://::1:443/" (URI::InvalidURIError)

やっぱりできないかー。と思って、やっぱりできないかー。という姿勢をしていたら、だいじょうぶですか?とお声がけいただきました。ありがたいありがたい!これは絶望ではなく希望の姿勢なのです。

一緒の部屋に居るのすごい

そんなこんなで、気づいたことを口頭でご報告して、uriライブラリについては報告先を推薦していただいて、20分間ほどで新規のIssueの提出までさせていただいてしまったのでした。

プルリクエストにできるといいな。

  1. 今回はヘルパーへの応募が当たったので、裏方としてかなり楽しませていただいたのでした。