【Rails】undefined method ‘〇〇’ for nil:NilClass【デイトラ】

本記事はこんな方向けに書いています!

  • とにかくRailsのエラーが出て困っている方
  • エラーが出た際に何をチェックすれば分からない方
  • なぜエラーが出たのか分からない方

エラー画面が出たら『どうして良いか分からない!』と感じているRuby on Rails初心者の方もいるのではないでしょうか?

今回は頻繁に見かける『undefined method ‘〇〇’ for nil:NilClass』が発生する原因とチェックポイントを解説していきます。

ステップ① 『undefined method…』の内容を翻訳

今回発生したエラーの画面が下図です。
何やら『NoMethodError』と怒られています。

今回発生したエラー画面

エラー文を読めば『どの箇所でエラーが起きているのか?』分かるようになっているので、まずググる前に翻訳してみましょう!

英語に自信がない方は『Deepl』がおすすめですよ。プログラミング用語なども自然な日本語に訳してくれます。

参考:Deeplサイト

今回発生した『undefined method ‘tasks’ for nil:NilClass』は直訳すると、『Nilクラスのnilオブジェクトに対するtasksメソッドが定義されていない』という意味になります。

ちなみに『nil(ニル)』とは中身がないことを意味します。

犬

エラー文を訳したけどよく分からん!!

確かに直訳だと分かりづらいですよね!
先程のエラーの意味は、こんな風に解釈すると分かりやすいかと思います。

『対象のオブジェクトに対してtasksというメソッドを実行したいんだけど、そもそもオブジェクトが空だから実行できませんよ!』

中身がないものに対して、tasksというメソッドを実行していたからエラーが発生していたんだと分かります。

ステップ② 『undefined method…』のコードを確認

では、問題のコードを見てみましょう。今回エラーが発生しているのが、Boardコントローラーのshowアクションの部分です。

class BoardsController < ApplicationController
    before_action :authenticate_user!

==途中コード省略==
    def show
        @tasks = @board.tasks
    end
==途中コード省略==
end

@tasks = @board.tasksでBoardに紐づくTaskの一覧を取れるようにしています。

しかし@boardがshowアクション内で定義されていないので、『@boardって何?』とRailsが解釈できなくなり、結果的に@boardがnilになってしまうわけです。

ですのでちゃんと『@boardとは〇〇のことを指していますよ!』と教えてあげる記述が必要になります。

ステップ③ showアクションのコードを修正

次のコードのように@boardの記述を追加しました。

class BoardsController < ApplicationController
    before_action :authenticate_user!

==途中コード省略==
    def show
        @board = Board.find(params[:id]) #追加
        @tasks = @board.tasks
    end
==途中コード省略==
end

ちなみに『find(params[:id])』はテーブル(データが入った表)から『id』で検索するという意味になります。

犬

たまに『params[:board_id]』みたいにparamsの中身が『:id』じゃない場合もあるよな!!

これはキーが主キーか外部キーの違いかで使い分けます。

例えば、今回のようにBoardテーブルが自分自身が持つキー(主キー)で検索します。そのため『:id』と書くだけでRailsはid = Boardのidなんだと解釈してくれます。

@board = Board.find(params[:id])

しかし次のコードではエラーが発生してしまいます。どこがおかしいのか分かるでしょうか?

【間違った例】

class TasksController < ApplicationController
  def show
    @board = Board.find(params[:id])
    @task = Task.find(params[:id])
  end
end

どこがおかしいかというと、『@board = Board.find(params[:id])』の部分です。この書き方だと[:id]はTaskテーブルが持つidとして捉えられてしまいます。

本来、[:id]はBoardテーブルのidであって欲しいはずですよね?

逆に『@task = Task.find(params[:id])』は問題ありません。
ここでの[:id]はTaskテーブルのidとなります。

【正しい例】

class TasksController < ApplicationController
  def show
    @board = Board.find(params[:board_id]) #ここを修正
    @task = Task.find(params[:id])
  end
end


params[:id]を使用する際は、どのコントローラーでそのidを使おうとしているのか確認するようにしましょう!

本記事のまとめ

『undefined method ‘〇〇’ for nil:NilClass』のエラーは、〇〇のメソッドを実行する対象(オブジェクト)がnilになっているため起きてしまいます。

オブジェクトがしっかり定義されているか?等を重点的に見ると良いかと思います!!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です