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開発するときにどんどん活用してみてください。
以上です。ありがとうございました!