その他
    ホーム 技術発信 DoRuby Railsのエラー画面への処理を読む

    Railsのエラー画面への処理を読む

    この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

    こんにちは。T氏です。 今日はRailsのエラー画面(public/404.htmlや500.html)への遷移はどうやってされているかをご紹介します。

    エラー画面への制御は、actionpackrescue.rbで行っています。
    *今回はactionpack-2.1.2である事前提に話を進めます。

     
    では、処理が行われている実際のコードを抜き出して見てみましょう。
     

    まず、Exceptionが発生するとrescue.rbのrescue_actionが呼び出されます。
    ここではlocalhostか判定をして表示するviewの振り分けをしています。

          def rescue_action(exception)
            # logへの出力
            log_error(exception) if logger
            erase_results if performed?

            # Let the exception alter the response if it wants.
            # For example, MethodNotAllowed sets the Allow header.
            if exception.respond_to?(:handle_response!)
              exception.handle_response!(response)
            end

            # ここで判定をして、表示するエラー画面を切り分けている
            if consider_all_requests_local || local_request?
              # localhostだとこちら
              rescue_action_locally(exception)
            else
              # public以下の[status_code].htmlが呼ばれる
              rescue_action_in_public(exception)
            end
          end

     

    次にlocalhostの場合に呼び出されるrescue_action_locallyを見てみましょう。
    開発中によく見かけるエラー画面を出力しています。

          def rescue_action_locally(exception)
            add_variables_to_assigns
            # インスタンスに対してエラー文言やファイル名等をセットしている
            @template.instance_variable_set(“@exception”, exception)
            @template.instance_variable_set(“@rescues_path”, File.dirname(rescues_path(“stub”)))
            @template.send!(:assign_variables_from_controller)

            @template.instance_variable_set(“@contents”, @template.render_file(template_path_for_local_rescue(exception), false))

            # content_typeの指定
            response.content_type = Mime::HTML
            # rescues_pathではrescue.rbがあるディレクトリの下にあるlayout.erbを呼び出している
            render_for_file(rescues_path(“layout”), response_code_for_rescue(exception))
          end

     

    最後に、rescue_action_in_publicメソッドを見てみましょう。
    ここではファイル指定( [RAILS_ROOT]/public/[STATUS_CODE].html )をしています。

          def rescue_action_in_public(exception) #:doc:
            render_optional_error_file response_code_for_rescue(exception)
          end

          def render_optional_error_file(status_code)
            status = interpret_status(status_code)
            # pathとファイル名を指定している
            path = “#{Rails.public_path}/#{status[0,3]}.html”
            if File.exist?(path)
              # renderするファイルとステータスコードを指定
              render :file => path, :status => status
            else
              head status
            end
          end

     

    以上がRailsのエラー画面への制御でした。