NoMethodError -よく発生するRubyの例外クラス-


はじめに

初学者です。おそらく一番悩まされたエラーなので備忘録としてまとめました。
間違いあればご指摘お願いします!

追記 3/16 問題点の提示して頂きましたので修正しました!

修正箇所

nilClassについて修正いたしました。
参考記事様

参考記事様「NoMethodError・nil:NilClass」の原因
参考文献 「プロを目指す人のためのRuby入門」

NoMethodError

存在しないメソッドを呼び出そうとしているときに発生します。

考えられる原因はいくつかあります。

  • メソッド名を間違えちゃったパターン & レシーバが想定に対してnilになっているパターン
  • レシーバ(※1)の型(クラス)が想定していた型じゃないパターン

(※1)レシーバについて

対処法

  • ControllerとViewでスペルミスが無いか確認する
  • Controllerでコードの書き間違いが無いか確認する
  • そのページで対象のアクション(method)が定義されているか、インスタンス変数の(流れ)順番を意識して見なおす

対処法を確認したところで、詳細を見ていきます。

メソッド名を間違えちゃったパターン & レシーバが想定に対してnilになっているパターン[nil:NilClass]

メソッドがない = 指定しているメソッドの表記が間違えているというパターン

メソッドを定義しているController,Viewを確認すると間違いが見つかるのでは無いかと思います。
初学者の自分はよく単数形と複数形を間違えていました。
あとインスタンス変数の@を書き忘れてた時、場合によってはNoMethodErrorになります。

例を見ていきます!
下記の表記はよくあるコメント投稿サイトの一部です。
ここで両サイドにあるインスタンス変数に注目してください。

posts_controller

def index
   @posts = Post.all.order
end
index.html.erb
<% @posts.each do |post| %>  
  <div class="post" data-id=<%= post.id %> data-check=<%= post.checked %>>
    ・
    ・ 省略してます
    ・
  </div>
<% end %>

上記ではすでにコントローラーにて@postsが定義されています。ここでコントローラーの表記を間違えたとします。

posts_controller

def index
   posts = Post.all.order #インスタンスでなくローカルで定義したとします。(@の忘れ)
end
index.html.erb
<% @posts.each do |post| %>  
  <div class="post" data-id=<%= post.id %> data-check=<%= post.checked %>>
    ・
    ・ 省略してます
    ・
  </div>
<% end %>

これではコントローラーがposts(ローカル)なのに対し、ビュー側が@postsとなり、eachで表示しようとしています。
この場合NoMethodErrorになりました。

NilClassについて

nil とは、何かが存在しないことを表すために用いられるオブジェクトのことを指します。

nilは「NilClassクラスのオブジェクト」なので、「NilClass」クラスに定義されていないメソッドを使用すると、エラーが発生します。

上記のエラー文の「undefined method 'each' for nil:NilClass」に注目します。
直訳すると「nil:NilClassに対して、'each' は未定義のメソッドです」という意味です。

このエラーの原因は、@以外にも以下のようなスペルミスがないか入念なチェックが必要かと。

正解
@name.length
間違い
@neme.length

レシーバのクラスが想定していた型じゃないパターン

文字列でなくシンボル型で呼び出してしまったというのがよくあるパターンです
そんなことで!?ということでもやらかしてしまうのコワイ...(-_-)