ホーム 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のエラー画面への制御でした。

記事を共有

最近人気な記事