一分一秒真剣勝負!

Ruby, Railsなど。Web系の技術ネタを充実させたい・・が、そうなるかは分からない。

Railsのエラーハンドリング

Rails3.2から結構いい感じになったエラーハンドリング

Railsは1.xからやっているけど、気に喰わないのがエラーハンドリング周りだった。 特にRoutingエラーを補足する為に各バージョンごとに対応が微妙に違ったりして、毎回調べたりRailsの実装を追っていた記憶がある。 だけどRails3.2から実装された機能で、個人的にはこれで落ち着いたかなと思えた。 既に4が出ているので今更感があるけど、備忘録として書いておく。 Rails4.0.2,Ruby2.0.0で確認しています。

Release Notesでは以下のように書かれている。

Added config.exceptions_app to set the exceptions application invoked
by the ShowException middleware when an exception happens.
Defaults to ActionDispatch::PublicExceptions.new(Rails.public_path).

つまり、例外発生時に呼ばれる例外処理アプリケーションを config.exceptions_app で設定できるようになった。 デフォルトではActionDispatch::PublicExceptions.new(Rails.public_path)が設定される。

どうやって使うか

色々と調べた結果、ActionDispatch::Routing::RouteSetをセットしてやるのが一番シンプルかなーと思った。 まずはself.routesをセット。

# config/application.rb
config.exceptions_app = self.routes #=>ActionDispatch::Routing::RouteSet

で、例外処理用のコントローラを作成しておく。

# app/controllers/erros_controller.rb
class ErrorsController < ApplicationController
  def not_found
    render status: 404
  end

  def internal_server_error
    render status: 500
  end
end

最後にroutes.rbで各httpステータスコードを判定し、ErrorsControllerの各メソッドを指定してやる。

# config/routes.rb
  get '/404', to: 'errors#not_found'
  get '/500', to: 'errors#internal_error'

他のやり方

self.routes以外を指定する事も当然出来る。 というかRackアプリを指定できるのでRailsで無くてもOKです。 例えば以下の様な感じ。

# config/application.rb
config.exceptions_app = ->(env) { ErrorsController.action(:error_page).call(env) }

明確にエラーコードを表示したいウェブアプリだと使うかも。

思うこと

エラーハンドリングに関してはRails newした時に雛形を作るなどしてしまってもいいのではと思った。フリーランスで働いていた時に、途中から入ったプロジェクトの場合、エラーハンドリングの実装方法がバラバラで、その内容によっては無駄に工数がかかるケースもあったので。 ま、Rails is omakaseなので嫌なら使うなって話ですが。