ホーム › エラー解決 › Ruby › NoMethodError
Ruby ERROR

Ruby NoMethodError: undefined method の解決法

そのオブジェクトに無いメソッドを呼んだときのエラーです。nilに対する呼び出しが特に多いです。

このエラーメッセージ

NoMethodError: undefined method `+' for nil

原因

❌ エラーになるコード

NG
total = nil
[1, 2, 3].each { |n| total = total + n }
puts total

✅ 修正したコード

OK
total = 0
[1, 2, 3].each { |n| total = total + n }
puts total   # 6
▶ 修正済みコードを実行エディタで開く
progoのRuby実行環境(インストール不要・登録不要)でその場で動作を確認できます。

解決のポイント

「undefined method for nil」は、変数がnilなのにメソッドを呼んでいるサインです。合計変数はtotal = 0で初期化します。&.(ぼっち演算子)を使えばnilのとき呼び出しをスキップできます。

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

undefined method `foo' for nil:NilClass のfor のうしろがレシーバ(呼び出された相手)の型です。for nil:NilClass なら相手がnil、for an instance of String(Ruby 3.4以降)や for "abc":String(3.3以前)なら相手が文字列、という意味です。まず「どの変数が」その型になっているかを特定します。

user = nil
puts user.name
# undefined method `name' for nil  ← user が nil

型別の対処法

NoMethodError と NameError の違い

undefined local variable or method `x' はNameErrorで、名前そのものが存在しません(スペルミスや未定義)。undefined method `x' for ... のNoMethodErrorは、相手のオブジェクトは存在するがそのメソッドを持っていない状態です。エラークラス名で切り分けます。

# NameError(変数が無い)
puts total

# NoMethodError(相手はいるがメソッドが無い)
puts 5.push(3)

private method called for でも出る

private method `foo' called for an instance of Bar は、privateメソッドを obj.foo の形(レシーバ付き)で呼んだときに出ます。private メソッドはレシーバを付けずに foo と呼ぶか、send(:foo) を使います。

存在確認してから呼ぶ

val = data&.dig(:user, :name)   # 途中がnilでも安全
puts val || "名前なし"

obj = "text"
puts obj.upcase if obj.respond_to?(:upcase)
▶ &.(ぼっち演算子)とrespond_to?を実行エディタで開く
progoのRuby実行環境(インストール不要・登録不要)でその場で動作を確認できます。

よくある質問

nil? で確認できる?
はい。x.nil? で判定できます。x&.method で安全に呼べます。
配列.sumではダメ?
[1,2,3].sum と書けば初期化不要で合計できます。
undefined method for nil:NilClass の意味は?
呼び出した相手(レシーバ)が nil だったという意味です。for のうしろが相手の型です。nil を返しているのがどの変数・式かを追い、初期値を入れるか &. で回避します。
private method called for が出る
private メソッドをレシーバ付き(obj.method)で呼んでいます。obj を付けずに method と呼ぶか、send(:method) を使います。
NameError(undefined local variable or method)との違いは?
NameError は名前自体が存在しない状態、NoMethodError は相手は存在するがそのメソッドを持っていない状態です。エラークラス名で切り分けます。