39

RESTful API を介して通信される JSON を使用する「サービスとしてのソフトウェア」アプリがあります。

簡単に言えば、JSON データ交換で RESTful API を使用するときに例外をキャプチャして報告するためのベスト プラクティスは何ですか?

私が最初に考えたのは、Rails が scaffold を生成することによって何をするかを見ることでしたが、それは明らかに正しくありません。ここに抜粋があります:

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 でエラー ページをレンダリングします。しかし、JSON を期待しているクライアントにとって HTML は役に立ちません。

Mumble.find() をbegin ... rescue RuntimeErrorブロックでラップし、JSON status => :unprocessable_entity などをレンダリングすることで、これを回避できます。

しかし、クライアントのアプリが無効なパスを送信した場合はどうなるでしょうか。

http://www.myhost.com/badtypo/1.json

JSON ベースのアプリはそれをキャッチして JSON でエラーを返すことになっていますか? もしそうなら、ActionDispatchを深く掘り下げることなく、どこでそれをキャプチャできますか?

全体として、エラーが発生した場合、パントして ActionController に HTML を生成させますか? それは気分が悪い...

4

4 に答える 4

77

([質問を投稿]を押す直前に答えを見つけました。しかし、これは他の誰かにも役立つかもしれません...)

ActionControllerを使用するrescue_from

答えは、このガイドで説明され、ここrescue_fromに記載されているように、ActionControllerを使用することです。特に、次の行に沿って、デフォルトの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
于 2012-08-08T07:21:00.667 に答える
7

それが誰かを助けるなら、これは私の純粋なjson APIのキャッチオールとして私がしたことです:

特定の各コントローラーが継承するあなたApplicationControllerに、追加します

# app/controllers/api/v1/application_controller.rb

# ...

rescue_from StandardError do |exception|
    render json: { :error => exception.message }, :status => 500
end

# ...
  • 主に恐れのない愚か者の答えに基づいています
于 2016-03-24T08:48:57.367 に答える
4

開発者として、トレースも見たいと思うでしょう (できれば便利な行で、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
于 2016-10-14T13:20:04.727 に答える
1

JSON API コードを記述するための一貫した標準を維持する方法について明確なコンセンサスはありませんが、これは私が実践していることの一部です (あなたが要求した以上のものです):

  1. シンプルに保つ - 休息を心がけましょう。カスタム メソッドを使用すると、複雑なものをすばやく作成できます。
  2. サーバーにネイティブ エラー コードを返させ、「rescue_from」を使用してキャプチャし、
  3. それ以外の場合は、Rails HTTP 応答コードをレンダリングします。これは、クライアント アプリによって明確にターゲットにすることができます。

あなたの場合、Railsの Respond_to と Respond_with が html/json/other の応答を適切に処理していることがわかります。また、ソリューションでも効果的に HTML をレンダリングしますが、それはクライアント アプリによって解釈されるものではなく、代わりに HTTP ヘッダーを読み取り、「rescue_from」をトリガーする HTTP 応答コードを取得します。 .

于 2012-08-08T07:41:39.287 に答える