プログラミング学習 備忘録

Railsを学習していく上での技術メモ。学んだことや解決したエラーなどを記録していきます。

例外処理と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: truefalseに変える事で本番環境用のエラー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つだと考えていたのであまり気にした事がなかった。 今回の例外処理の実装を通してようやく点と点が繋がった。