TL;DR
Webアプリケーションを作成して行く段階でエラーが出るのはつきもの!
そのなかで、いかにエラーとしっかり向き合うかが重要かと個人的には思っております!
今回は、あるあるのエラーを何個か抜粋して解説していきます。
2020/04/19 編集点 ↓
Loggerの使い方を追記しました。
##エラー文
undefined method 'id' for nil:NilClass
例えば、すごく簡素的な例ですが、
def update
@tweet = Tweet.find(params[:id])
if @tweet.update(tweet_params)
...
end
みたいなコードがあったとしましょう!
このとき、undefined method 'update' for nil:NilClass
とエラーが出たと仮定します!
この意味としては、NilClass
のnil
オブジェクトに対して、update
メソッドは定義されていないよ!ってことです。
つまり、@tweet
がnil
になっているということです!
find
メソッドは、見つからなかった場合にnil
オブジェクトを返します。
そのため、このような簡素的なコードでは、エラーが起こりにくいかもしれませんが、
Usecases
やServices
などのようにディレクトリを分岐させていった時に直面するので、find
メソッドを使った時は、@tweet.present?
を書いてハンドリングすることをお勧めします。
undefined local variable or method
これもあるあるで、エラー文で示された行に未定義の変数、もしくはメソッドがあると言うことですね!
よくあるのは、"hello"
のようなString型のオブジェクトを返したかったにも関わらず、hello
と変数もしくはメソッドにしてしまっていた、、、などがあると思います。
RoutingError (No route matches [GET] "/tweets")
単に、URIにマッチするRoutingが存在していない!ということです。
しかし、これに関しては、たまに起こると思います!
特にdevise
で Userサインアップ、サインインのルーティングが存在している時に、usersコントローラを作成し、usersコントローラのルーティングをdeviseのルーティングの前に記述すると、users/:id
のルーティングの時にエラーになるので気をつけましょう。
ActiveRecord::NodatabaseError
データベースが存在しない時に出るエラーです。
$ bundle exec rails db:create # Rails ver5以降
$ bundle exec rake db:create # Rails ver5以前
したら治ると思います!
SyntaxError
単純に文法のミスです!
タイプミスをしていないかの確認、修正でいいと思います。
ActionView::MissingTemplete
該当するViewが存在していないよ〜ってことですね!
コントローラに対するViewが存在するかを確認してください!
render
などを用いると発生しやすいと思います。
ArgumentError
そもそも、Argument
は引数
のことですので、
メソッドの引数の数などが正しいことを確認しましょう!
個人的に行なっている対策
-
logger
を使う!(Rails.logger.debug
というメソッドが使えます。) *1(下に追記があります) -
binding.pry
で止めて、メソッドの返り値を確認する。 -
tail -f log/development.log
を入力し、ログを確認(RSpecの場合はtest.log
) - logに出力された、SQLを読む
- どの部分のなんのエラーかを正確に見極める。
Loggerの使い方(2020/04/19追記部分)
一般的なTweetsController#create
を例に解説させていただきます。
class TweetsController < ApplicationController
...
def create
@tweet = tweet.new(tweet_params) # *1
if @tweet.save
flash[:success] = "ツイートを作成しました"
redirect_to tweets_path
else
flash.now[:danger] = @tweet.errors.full_messages
render :new
end
end
...
end
このときに「*1
の@tweet
の中身が知りたい!」なんてことがあると思います!
そんなときに以下の1行を追加すると、中身がわかると思います!
...
@tweet = tweet.new(tweet_params) # *1
Rails.logger.debug "@tweet : #{@tweet.inspect}" # この1行を追加
if @tweet.save
...
inspect
メソッドは、オブジェクトの中身を標準出力してくれるメソッドです。
これでcreate
アクションが走ると、development.log
に以下のように出力されると思います。
@tweet : #<Tweet id: nil, user_id: 1, content: "Qiitaの記事用のツイートです", image_data: "{
\"id\":\"1b73ccb4ded451d874761e038a5dfe73.png\",\"stor...", created_at: nil,updated_
at: nil, tweet_id: nil>
こうすることで、@tweet.content
などの中身を知ることができます!
このlogger
メソッドは、サービス層でも利用可能なので、Rails開発するときにどんどん活用してみてください。
以上です。ありがとうございました!