railsのルーティングエラーを捕捉する

特に何も設定せずとも routes.rb にマッチしなかったリクエストは rails がエラーにしてくれますが、ログに書き出す等の特別な処理を差し込みたい時にはルーティングエラーを捕捉する必要があります。

少々苦戦したので、忘れないようにメモしておきます。 環境はRails 4.2.1ですが、4系なら同じ振る舞いになるはず。たぶん。

routes.rb

末尾に以下の行を追加すると、マッチしなかった全GETリクエストを raise_not_found! アクションで拾えるようになります。

get  '*unmatched_route', to: 'application#raise_not_found!', format: false

application_controller.rb

application_controller は例えば以下のような感じで。

  def raise_not_found!
    e = ActionController::RoutingError.new("No route matches #{params[:unmatched_route]}")
    render_404(e)
  end

  private

  def render_404(e)
    logger.warn e
    render file: "public/404.html", status: :not_found, layout: false
  end