コード懇親会 at RubyKaigi 2026でdRubyに触る
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_uriがdruby://::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の提出までさせていただいてしまったのでした。
プルリクエストにできるといいな。