RESTful APIを介して通信されるJSONを使用する「サービスとしてのソフトウェア」アプリがあります。
簡単に言うと、JSONデータ交換でRESTful APIを使用する場合の例外のキャプチャとレポートのベストプラクティスは何ですか?
私の最初の考えは、Railsが足場を生成することによって何を行うかを確認することでしたが、それは明らかに正しくありません。ここに抜粋があります:
class MumblesController < ApplicationController
# GET /mumbles/1
# GET /mumbles/1.json
def show
@mumble = Mumble.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: @mumble }
end
end
end
この場合、JSONコードが存在しないIDを送信するとします。
http://www.myhost.com/mumbles/99999.json
次に、Mumble.find()はActiveRecord :: RecordNotFoundを発生させます。 ActionControllerはそれをキャッチし、エラーページをHTMLでレンダリングします。しかし、HTMLはJSONを期待しているクライアントには役に立たない。
Mumble.find()をbegin ... rescue RuntimeError
ブロックでラップし、JSONステータス=>:unprocessable_entityなどをレンダリングすることで、これを回避できます。
しかし、クライアントのアプリが無効なパスを送信した場合はどうなりますか。例:
http://www.myhost.com/badtypo/1.json
JSONベースのアプリはそれをキャッチしてJSONでエラーを返すことになっていますか?その場合、ActionDispatchを深く掘り下げることなく、どこでそれをキャプチャできますか?
全体として、エラーが発生した場合、パントしてActionControllerにHTMLを生成させますか?それは正しくないと思います...
([質問を投稿]を押す直前に答えが見つかりました。しかし、これは他の人にも役立つかもしれません...)
rescue_from
を使用します答えは、ActionControllerのrescue_from
を使用することです。説明は このガイドで と記載されています ここ 。特に、デフォルトの404.htmlおよび500.htmlファイルのデフォルトのレンダリングを次のように置き換えることができます。
class ApplicationController < ActionController::Base
rescue_from ActiveRecord::RecordNotFound, :with => :record_not_found
private
def record_not_found(error)
render :json => {:error => error.message}, :status => :not_found
end
end
それが誰かを助けるなら、これは私が純粋にjson apiのすべてをキャッチするために私がしたことです:
特定の各コントローラーが継承するApplicationController
に、以下を追加します
# app/controllers/api/v1/application_controller.rb
# ...
rescue_from StandardError do |exception|
render json: { :error => exception.message }, :status => 500
end
# ...
開発者は、トレースも確認する必要があります(できれば、有用な行を使用して、gemを除外します)。そして、生産のためにトレースを見えなくします:
rescue_from StandardError do |exception|
# Handle only JSON requests
raise unless request.format.json?
err = {error: exception.message}
err[:backtrace] = exception.backtrace.select do |line|
# filter out non-significant lines:
%w(/gems/ /rubygems/ /lib/Ruby/).all? do |litter|
not line.include?(litter)
end
end if Rails.env.development? and exception.is_a? Exception
# duplicate exception output to console:
STDERR.puts ['ERROR:', err[:error], '']
.concat(err[:backtrace] || []).join "\n"
render :json => err, :status => 500
end
JSON APIコードを作成するための一貫した標準を維持する方法について明確なコンセンサスはありませんが、これは私が実践していることの一部です(あなたが要求したものよりも):
あなたの場合、Rails respond_toとrespond_withがhtml/json /その他の応答を適切に処理します。ソリューションでも、HTMLを効果的にレンダリングしますが、これはクライアントアプリによって解釈され、代わりにHTTPヘッダーを読み取り、HTTP応答コードを取得します。これが「rescue_from」をトリガーしているものです。