web-dev-qa-db-ja.com

Rails 4:アセットパイプラインを使用するカスタム404ページを作成するにはどうすればよいですか?

カスタマイズされたエラー処理ページを作成するための多くのソリューションがありますが、Rails 4:

人々に変更を促す標準的な答え404.html in /publicは、アセットパイプラインにあるCSSテーマを使用したいので、機能しません。 htmlファイルがアセットパイプラインで定義されたスタイルにアクセスできる方法はありますか?そうでない場合、パイプラインにアクセスできるカスタムエラーハンドラを作成する方法は?

26
Avery

For Rails 4.1 I like この答えは、資産タイプを追加します 良いですが、試していません。OnRails 4.0。 8、これらの3つの参照は私を助けました:

  1. 動的エラーページ は、質問の2番目の参照です。これは私にとってはうまくいきました。

  2. カスタムエラーページ は、最初の参照から、またはその逆方向に移動した可能性がありますが、Capybaraでのテストに関する情報を追加することにより、さらに1マイル進みます。

  3. テスト構成を変更したくなかったため、Capybaraのテストは行いませんでした。ただし、 RSpec-Rails Request Specs は、これらの要求を個別にテストし、それらが完了して正しいコンテンツを返すことを確認するために私を集めました。

以下は、3つの参考文献が教えていることの簡単な説明です。

  1. 次の設定をconfig/environments/production.rbに追加します

    # Route exceptions to the application router vs. default
    config.exceptions_app = self.routes
    
  2. ルーティング構成config/routes.rbを編集して、エラーページをエラーコントローラーに送信します。

      # error pages
      %w( 404 422 500 503 ).each do |code|
        get code, :to => "errors#show", :code => code
      end
    

    ステータスコードの値を持つパラメーターshowを使用して、404、422、500、および503ページ要求をerrorsコントローラーのcodeアクションにルーティングします。

  3. コントローラーapp/controllers/errors_controller.rbを作成します。コンテンツ全体は次のとおりです。

    class ErrorsController < ApplicationController
    
      def show
        status_code = params[:code] || 500
        flash.alert = "Status #{status_code}"
        render status_code.to_s, status: status_code
      end
    
    end
    

    私の好みはflash.alertにステータスメッセージを設定することでした

  4. ページ自体を作成します。 .erbを使用しますここにapp/views/errors/500.html.erbがあります

    <p>Our apology.  Your request caused an error.</p>
    <%= render 'product_description' %>
    

    パーシャルをレンダリングできることがわかります。ページは、app/views/layouts/application.html.erbのすべてのレイアウトボイラープレートまたは設定した他のレイアウトボイラープレートでレンダリングされます。これには、フラッシュからのステータスメッセージを表示する<div id='alert'><%= alert %></div>が含まれます。

  5. テストファイルspec/requests/errors_request_spec.rbを追加して、RSpecでテストしました。以下は、500ステータスページのテストを示すそのファイルの省略されたコンテンツです。

    require 'Rails_helper'
    
    RSpec.describe "errors", :type => :request do
    
      it "displays the 500 page" do
        get "/500"
        assert_select 'div#alert', 'Status 500'
        assert_select 'div[itemtype]'
      end
    
    end
    

    最初のアサーションは、フラッシュアラートをチェックします。 2番目のアサーションはパーシャルをチェックします。

43
Douglas Lovell

これを行うgemを作成しました: exception_handler

素晴らしいチュートリアルもあります here

また、このテーマに関する広範な回答を書いた こちら

ミドルウェア

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

コントローラー

# app/controllers/exception_controller.rb
class ExceptionController < ApplicationController
  respond_to :json, :js, :html
  before_action :set_status

  def show
    respond_with @status
  end

  private

  def set_status
    def status
      @exception = env['action_dispatch.exception']
      @status    = ActionDispatch::ExceptionWrapper.new(env, @exception).status_code
      @response  = ActionDispatch::ExceptionWrapper.rescue_responses[@exception.class.name]
    end
  end
end

表示

# app/views/exception/show.html.erb
<h1>404 error</h1>

これは非常にシンプルなバージョンです-必要に応じて詳細を説明できます。

基本的に、 config.exceptions_app ミドルウェア、middlewareスタック内の例外をキャプチャし(環境全体をレンダリングするのではなく)、独自のcontroller#action

あなたがコメントした場合、私はあなたが望むなら、さらにあなたを助けます!

5
Richard Peck