79

Rails アプリで通常の HTML フロントエンドと JSON API を使用しています。これで、誰かが呼び出す/api/not_existent_method.jsonと、デフォルトの HTML 404 ページが返されます。{"error": "not_found"}HTMLフロントエンドの元の404ページをそのまま残しながら、これを次のように変更する方法はありますか?

4

4 に答える 4

117

ある友人が、404 エラーだけでなく 500 エラーも処理するエレガントなソリューションを教えてくれました。実際、すべてのエラーを処理します。重要なのは、すべてのエラーが例外を生成し、それがいずれかによって処理されるまで、ラック ミドルウェアのスタックを介して上方に伝播することです。さらに詳しく知りたい場合は、この優れたスクリーンキャストをご覧ください。Rails には例外用の独自のハンドラーがありますが、あまり文書化されていないexceptions_app構成オプションでオーバーライドできます。これで、独自のミドルウェアを作成するか、次のようにエラーをレールに戻すことができます。

# In your config/application.rb
config.exceptions_app = self.routes

次に、次のルートでこれらのルートを一致させる必要がありますconfig/routes.rb

get "/404" => "errors#not_found"
get "/500" => "errors#exception"

そして、これを処理するためのコントローラーを作成するだけです。

class ErrorsController < ActionController::Base
  def not_found
    if env["REQUEST_PATH"] =~ /^\/api/
      render :json => {:error => "not-found"}.to_json, :status => 404
    else
      render :text => "404 Not found", :status => 404 # You can render your own template here
    end
  end

  def exception
    if env["REQUEST_PATH"] =~ /^\/api/
      render :json => {:error => "internal-server-error"}.to_json, :status => 500
    else
      render :text => "500 Internal Server Error", :status => 500 # You can render your own template here
    end
  end
end

最後にもう 1 つ付け加えておきます。開発環境では、Rails は通常、404 または 500 ページをレンダリングせず、代わりにバックトレースを出力します。開発モードでの動作を確認したい場合は、ファイルErrorsControllerのバックトレースを無効にしてください。config/enviroments/development.rb

config.consider_all_requests_local = false
于 2012-04-21T08:37:07.517 に答える
11

確かに、次のようになります。

class ApplicationController < ActionController::Base
  rescue_from NotFoundException, :with => :not_found
  ...

  def not_found
    respond_to do |format|
      format.html { render :file => File.join(Rails.root, 'public', '404.html') }
      format.json { render :text => '{"error": "not_found"}' }
    end
  end
end

NotFoundException例外の実際の名前ではありません。Railsのバージョンと必要な動作によって異なります。Google検索で見つけるのはかなり簡単です。

于 2012-04-20T21:32:27.123 に答える
6

あなたの最後に置くようにしてくださいroutes.rb

match '*foo', :format => true, :constraints => {:format => :json}, :to => lambda {|env| [404, {}, ['{"error": "not_found"}']] }
于 2012-04-20T21:48:33.633 に答える