例外処理とSlack通知の実装
掲示板アプリ制作の締め括りに、例外処理及び500エラーが出た際にSlackに通知が飛ぶようにしました。
実装を通して学んだことを記します。
参考にさせていただいた記事
slack-notifierでrailsからSlackへ簡単にメッセージを送る - Qiita
【Rails】500番エラーをslack通知する - Qiita
Railsアプリの例外ハンドリングとエラーページの表示についてまとめてみた - Qiita
学んだ事
Credentialsについて
Rails5.2から追加された機密情報を保持する仕組み。 Credential.yml.encという秘匿情報を記録するファイルと、 Master.keyという秘匿情報を閲覧したり、編集したりするための鍵となるファイルが要
$ EDITOR='vi' bundle exec rails credentials:edit
コマンドでmaster.keyを使ってvi
でcredential.yml.encを開く事ができる。
参考にさせていただいた記事
credentials.ymlの書き方 - annzuwatanuki’s diary
Railscredentials.yml.encについてまとめる - Qiita
開発環境でエラーを表示させる
開発環境ではデフォルトではそのままのエラー文が表示されている
config/environments/development.rb
内のconfig.consider_all_requests_local: true
をfalse
に変える事で本番環境用のエラーviewを表示できるようになる。
エラーの継承関係
エラーにも継承関係が存在し、exceptionが全ての親クラスである。
アプリケーション全体にエラーを適用したいときは、rescue_fromメソッドを使う。
# application_controller内 unless Rails.env.development? rescue_from Exception, with: :error_500 rescue_from ActiveRecord::RecordNotFound, with: :error_404 end def error_404 render file: Rails.root.join('public', '404.html'), layout: false, status: :not_found end def error_500(error) logger.error error logger.error error.backtrace.join("\n\n") render file: Rails.root.join('public', '500.html'), layout: false, status: :internal_server_error end
このとき、rescue_from
は必ず親クラスから記載する。これは、例外処理の際に下のコードから順に読み込むためであり、親クラスの例外処理であるrescue_from Exception, with: :error_500
を下に書いてしまうと全てerror_500として処理されてしまうため。
#この書き方でも同じように実装できる def error_404 render file: Rails.root.join('public', '404.html'), layout: false, status: :not_found end def error_500(error) logger.error error logger.error error.backtrace.join("\n\n") render file: Rails.root.join('public', '500.html'), layout: false, status: :internal_server_error end
ルーティングの記載
404_errorと500_errorのviewを表示させるためにルーティングを書く必要がある。このとき、必ずroutesの一番下に書く事!!
上の方に書いてしまうとほとんど全てのページで404エラーや500エラーが表示されてしまう。
#routes.rb内 . . . get '*path', to: 'application#error_404' get '*path', to: 'application#error_500'
エラー解決
存在しないページのURLに飛んだ際に、本来404_errorにならないといけないのに500_errorが表示されてしまうエラーが発生
アクセスしたページは、localhost:3000/boards/1000
config.consider_all_requests_local: true
に戻してエラー内容を見てみるとNo_method_errorになっている。
NoMethodError in BoardsController#show undefined method `comments' for nil:NilClass
404エラーにするためには、ActiveRecord::RecordNotFound
にしないといけない。
これはどうやら、
@board = Board.find_by(params[:id])
でfind_byメソッドを使っていた事が原因らしい。
find_byはidが存在しない場合はnilを返すため、@boardがnilになってしまっていたらしい。
@board = Board.find(params[:id])
に変更する事で無事ActiveRecord::RecordNotFound
を表示させる事ができた。
Railsチュートリアルの時からnilの概念と重要性について聞いてはいたが、結局はうまく動くか動かないかの2つだと考えていたのであまり気にした事がなかった。
今回の例外処理の実装を通してようやく点と点が繋がった。