🐕

【bugs.ruby Advent Calender 2025】TypeError が発生しない #dig を追加する【23日目】

に公開

bugs.ruby Advent Calender 2025 23日目の記事です。

これはなに

今年1年間通してみてきた bugs.ruby のチケットの中から気になったものを1つずつ取り上げていく Advent Calender です。
取り上げるチケットは基本的にこのブログで取り上げたものになります。
記事のまとめは ここを参照 してください。

[Feature #21545] #try_dig, a dig that returns early if it cannot dig deeper

  • #dig は参照するオブジェクトに #dig メソッドがないと次のように TypeError が発生します。
{ a: "foo" }.dig(:a, :b)
# => error: String does not have #dig method (TypeError)

これを『 #dig メソッドがない場合は nil を返す』という #try_dig を追加する提案です。
具体的には次のような場合に利用したい想定ですね。

# こっちはデータ構造的に問題はない
api_response = { status: { code: 200 } }
api_response.try_dig(:status, :code) # => 200

# 特定のデータの場合にはエラーにならず nil になってほしい
api_response = { status: "ok" }
api_response.try_dig(:status, :code) # => nil

#dig に関して定期的に提案が上がってくるんですが例えば過去には『要素がない場合は例外にする』みたいな話とかも上がってました。

あとは今年の Advent Calender でも取り上げたんですが以下のような話もありましたね。

[Feature #21358] のチケットでも書かれたりしているんですがこのあたりのプレーンなデータ構造であれば #dig よりもパターンマッチで解決できるならそっちで解決すればいいのではと最近思ったりしています。
今回のチケットでも以下のようなパターンマッチを利用した代替案がコメントで提示されていたりしますね。

def match(input)
  case input
  in { status: { code: Integer => status } }
    puts "Status code: #{status}"
  in { status: status }
    puts "Other status: #{status}"
  else
    raise "mismatch: #{input}"
  end
end

match({ status: "ok" })
match({ status: { code: 200 } })

パターンマッチはパターンマッチで制限があるので利用できない場面もあるんですがこういうコードのほうがどういうデータ構造なのかも認知しやすくてわかりやすいですね。

関連

GitHubで編集を提案

Discussion