シンボルキーのハッシュを文字列キーで参照すると nil になる
:name(シンボル)と"name"(文字列)は別のオブジェクトとして扱われるため、シンボルキーで作ったハッシュを文字列キーで参照すると見つからずnilが返ります。
なぜエラーが出ないのか
出力: nil
(エラーなし)- Rubyは何も報告しません。文法として正しいためです
出力: nil- 実際の挙動 — 期待した結果と食い違っている箇所
見つけ方- エラーが出ないので、出力を目で確かめるしかありません。この種の誤りが最も発見が遅れます
このエラーが出る典型パターン
パターン1
1 user = {name: "Taro"} 2 puts user["name"].inspect ^
出力: nil
:name(シンボル)と"name"(文字列)は別のオブジェクトです。シンボルキーのハッシュを文字列キーで探すと見つかりません。
直し方: "name" を :name にします。
広告
広告スロット(未設定)
パターン2
1 profile = {email: "taro@example.com"} 2 puts profile["email"].inspect ^
出力: nil
キーの見た目の文字が同じでも、シンボルと文字列はハッシュの中では別物として扱われます。
直し方: "email" を :email にします。
パターン3
1 config = {host: "localhost"} 2 puts config["host"].inspect ^
出力: nil
ハッシュリテラルで {host: ...} と書くと、キーは自動的にシンボル:hostになります。
直し方: "host" を :host にします。
パターン4
1 item = {sku: "A100"} 2 puts item["sku"].inspect ^
出力: nil
キーの型を取り違えると、存在するはずの値がnilとして扱われ、後続の処理でバグにつながります。
直し方: "sku" を :sku にします。
パターン5
1 ticket = {seat: "12A"} 2 puts ticket["seat"].inspect ^
出力: nil
ハッシュを作った側の書き方(シンボルか文字列か)に合わせてアクセスする必要があります。
直し方: "seat" を :seat にします。
よくある誤解
「キーの見た目の文字が同じなら、シンボルでも文字列でも同じキーとして扱われるはず」という思い込みは誤りです。ハッシュのキー照合はオブジェクトとしての等価性で行われるため、:nameと"name"は別のキーです。
まとめ
シンボルキーのハッシュを文字列キーで参照すると nil になるは中級でつまずきやすい項目です。上の5パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。