Code Fix

初級

undefined method for nil の原因と直し方

nilが入った変数に対してメソッドを呼び出そうとしたときに出るエラーです。値を取得し損ねた変数(見つからなかった検索結果など)をそのまま使うと、必ずここで止まります。

エラーメッセージの読み方

main.rb:3:in `<main>': undefined method `upcase' for nil (NoMethodError)
main.rb
ファイル名
3
行番号 — 実際にクラッシュした行
<main>
発生場所 — <main> ならトップレベル、メソッド名ならそのメソッドの中
NoMethodError
例外クラス — 何が起きたか。ここを検索するのが最短です
undefined method `upcase' for nil
詳細メッセージ — どの値が問題だったか

このエラーが出る典型パターン

パターン1

 1  users = ["taro", "hanako"]
 2  found = users.find { |u| u == "jiro  " }
                                      ^
 3  puts found.upcase
main.rb:3:in `<main>': undefined method `upcase' for nil (NoMethodError)

findは条件に一致する要素が無いとnilを返します。見つからなかった変数にメソッドを呼ぶとここで止まります。

直し方: jiro を hanako にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  scores = {math: "eighty", science: "ninety"}
 2  english = scores[:english]
                         ^
 3  puts english.upcase
main.rb:3:in `<main>': undefined method `upcase' for nil (NoMethodError)

ハッシュに存在しないキーでアクセスすると、エラーにならず静かにnilが返ります。

直し方: :english を :math にします。

この問題を解いてみる →

パターン3

 1  nums = [15.5, 42.2, 7.1]
 2  big = nums.detect { |n| n > 100 }
                                 ^
 3  puts big.round
main.rb:3:in `<main>': undefined method `round' for nil (NoMethodError)

条件に合う要素が無いとdetectはnilを返します。しきい値が高すぎて何も見つからないと、後の行でエラーになります。

直し方: 100 を 10 にします。

この問題を解いてみる →

パターン4

 1  config = {timeout: 30}
 2  retries = config[:retries]
                         ^
 3  puts retries + 1
main.rb:3:in `<main>': undefined method `+' for nil (NoMethodError)

ハッシュに登録されていないキーの値はnilです。nilに対する+も未定義のメソッド呼び出しになります。

直し方: :retries を :timeout にします。

この問題を解いてみる →

パターン5

 1  inventory = {"apple" => 5, "banana" => 3}
 2  count = inventory["orange"]
                          ^
 3  puts count + 1
main.rb:3:in `<main>': undefined method `+' for nil (NoMethodError)

在庫に無い商品名で検索すればnilが返ります。存在確認をせずに計算に使うとエラーになります。

直し方: orange を apple にします。

この問題を解いてみる →

よくある誤解

「変数に何か入っていればメソッドを呼べるはず」という思い込みは誤りです。nilは専用のクラスNilClassのオブジェクトで、upcaseのような文字列用メソッドは持っていません。

実務での勘所

Rubyの「あらゆるものはオブジェクトである」という哲学は、nilにも例外なく適用されています。nilはNilClassという専用のクラスの、れっきとしたオブジェクトであり、nil.class、nil.methods、nil.to_sのように、他のオブジェクトと同じ作法でメソッドを呼べます。ただしNilClassが持つメソッドはto_s、to_a、nil?など数個の限られたものだけで、upcaseのような文字列用メソッドは含まれていません。JavaやC#の「nullはオブジェクトではない特殊な無」という扱いとは違い、Rubyのエラーは通常のメソッド呼び出し失敗と同じ枠組みで説明されます。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)