Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

Railsの派手な例外ページのしくみ

レールを使用することの良い点の1つは、開発で問題が発生したときに、非常に優れたエラー詳細ページが表示されることです。アプリに関連する部分が強調表示された、素晴らしいバックトレースが得られます。投稿されたパラメータを確認したり、環境変数やセッション変数を調べたりできます。

今日は、これらの派手なエラーページがどのように機能するかを見ていきます。

Railsの派手な例外ページのしくみ

開いているアクションパックをクラックする

今日主に関係するファイルは、actionpack / lib / action_dispatch / middleware/debug_exceptions.rbです。これらの開発モードのエラーページを表示することになると、それは大部分の面倒な作業を行います。本番モードのエラー画面がどこから来るのか知りたい場合は、public_exceptions.rbをチェックしてください。

ラックミドルウェア

ラックミドルウェアに慣れていない場合、概念は単純です。これにより、HTTPリクエストがアプリに到達する前にインターセプトし、アプリの出力がユーザーに返される前にインターセプトすることができます。

これは、何も面白いことをしない単純なミドルウェアです。

class MyMiddleware
  def initialize(app)
    @app = app
  end

  def call(env)
    @app.call(env)
  end
end
ラックミドルウェアを介してすべての例外をレスキューする

アプリで発生する例外は、@ app.call()を呼び出した結果として発生します。したがって、ラックアプリですべての例外をレスキューするのは、ミドルウェアにレスキュー句を追加するのと同じくらい簡単です。

def call(env)
  @app.call(env)
rescue StandardError => exception
  # this is a method we have to provide to generate the exception page
  render_exception(env, exception)
end

callメソッドから返されたものはすべて、通常のWebページであるかのように扱われます。したがって、render_exceptionによって返されるコンテンツは、元の応答を置き換えます。

例外のレンダリング

ActionDispatch::DebugExceptionsからrender_exceptionメソッドを抜粋しました。ご覧のとおり、例外から関連データを取得し、ERBテンプレートにフィードするだけです。

def render_exception(env, exception)
  wrapper = ExceptionWrapper.new(env, exception)
  log_error(env, wrapper)

  if env['action_dispatch.show_detailed_exceptions']
    request = Request.new(env)
    template = ActionView::Base.new([RESCUES_TEMPLATE_PATH],
      request: request,
      exception: wrapper.exception,
      application_trace: wrapper.application_trace,
      framework_trace: wrapper.framework_trace,
      full_trace: wrapper.full_trace,
      routes_inspector: routes_inspector(exception),
      source_extract: wrapper.source_extract,
      line_number: wrapper.line_number,
      file: wrapper.file
    )
    file = "rescues/#{wrapper.rescue_template}"

    if request.xhr?
      body = template.render(template: file, layout: false, formats: [:text])
      format = "text/plain"
    else
      body = template.render(template: file, layout: 'rescues/layout')
      format = "text/html"
    end
    render(wrapper.status_code, body, format)
  else
    raise exception
  end
end

def render(status, body, format)
  [status, {'Content-Type' => "#{format}; charset=#{Response.default_charset}", 'Content-Length' => body.bytesize.to_s}, [body]]
end

その他の用途

このラックミドルウェアのトリックを使用して、例外を除いて多くの興味深いことを行うことができます。ここHoneybadgerでは、エラーをインターセプトしてAPIに記録するために使用しています。これを行うために使用するコードは次のとおりです。

def call(env)
  config.with_request(::Rack::Request.new(env)) do
    begin
      env['honeybadger.config'] = config
      response = @app.call(env)
    rescue Exception => raised
      env['honeybadger.error_id'] = notify_honeybadger(raised, env)
      raise
    end

    framework_exception = framework_exception(env)
    if framework_exception
      env['honeybadger.error_id'] = notify_honeybadger(framework_exception, env)
    end

    response
  end
ensure
  Honeybadger.context.clear!
end


  1. RailsでFlashメッセージを使用する方法

    フラッシュメッセージとは何ですか? フラッシュメッセージは、Railsアプリケーションのユーザーと情報を伝達する方法であり、ユーザーはアクションの結果として何が起こるかを知ることができます。 メッセージの例 : 「パスワードが正しく変更されました」(確認) 「ユーザーが見つかりません」(エラー) これらのフラッシュメッセージをコントローラーに設定してから、ビューにレンダリングします。その後、ユーザーはそれに応じて行動できます。 これがどのように機能するかを正確に学びましょう! フラッシュメッセージの使用方法 flashを使用して、これらの通知メッセージを操作できます ヘルパーメソ

  2. RailsアプリケーションでOmniAuth-Twitterを使用する方法

    このチュートリアルでは、アプリケーションのユーザーがTwitterアカウントを使用してログインできるようにする方法を学習します。これを行うには、OAuthなどのツールを使用すると簡単になります。 OmniAuthのTwitter戦略を含むOmniAuth-Twitterを利用します。 飛び込みましょう! はじめに Railsアプリケーションを生成することから始めます。ターミナルから、コマンドを実行して実行します。 rails new Tuts-Social -T Gemfileを開き、ブートストラップgemを追加します。 #Gemfile...gem bootstra