web-dev-qa-db-ja.com

jqueryは$ .ajaxでRails standard REST DELETE answer

そのような問題は新しいものではないかもしれませんが、私は同様のものを見つけませんでした。私はそのようなjQueryコードを持っています:

$.ajax({ 
  url : ('/people/'+id), 
  type : 'DELETE', 
  dataType : 'json', 
  success : function(e) {
    table.getItems(currentPage);
  }
});

私のRailsコントローラは次のようになります:

def destroy
    @person = Person.find(params[:id])
    @person.destroy

    respond_to do |format|
      format.html { redirect_to(people_url) }
      format.json  { render :json => @person, :status => :ok }
    end
end

これは機能しています。

しかし、(標準で生成された)以下を使用すると、successコールバックが呼び出されません。

def destroy
    @person = Person.find(params[:id])
    @person.destroy

    respond_to do |format|
      format.html { redirect_to(people_url) }
      format.json  { head :ok }
    end
end

Rails 3.0.3jQuery 1.4.2Firefox 3.6.13の下でテストされています。
Firebugは、そのクエリが実行され、どちらの場合も200 OKを返し、どちらの場合もアイテムが削除されると述べています。ただし、2番目のケースでは、コールバックは呼び出されません。

RESTに大きな違いはありますか?また、足場コントローラーを使用してjQueryを利用する方法はありますか?

58
sandrew

私はこれに数回遭遇しましたが、答えは一見単純です。

$ .ajax呼び出しでdataType : 'json'を使用しているため、jQueryはJSON応答を期待しています。 head :ok Railsは、単一のスペース( http://github.com/Rails/rails/issues/1742 )を含む応答を返します。 jQueryは有効なJSONとして受け入れません。

したがって、本当にエラーまたは200 OKヘッダーのいずれかが表示されることが予想される場合は、リクエストにdataType : 'html'を設定するだけで機能します(dataTypeを設定しない場合、jQueryはタイプが何であるかを推測しようとします応答ヘッダーなどに基づいており、jsonを推測することができますが、その場合でもこの問題が発生します)。実際にJSONが返されることを期待している場合は、head :okを使用する代わりに、JSONで有効なものをレンダリングするか(コメントを参照)、@ Waseemの提案に従ってhead :no_contentを使用します。

73
mtjhax

GearHeadは正しいですが、jQueryパーサーは実際には、空の文字列応答をnullとして扱い、解析しないように十分にスマートになっています。

ただし、jsonを受け取ったり、head応答を受け取ったりする呼び出しがあり、サーバーにアクセスできない場合や、すべてのhead呼び出しを変更したくない場合は、この代替ソリューション:

問題は、Railsがheadを使用すると空の応答として単一のスペースを送信することです(ここを参照してください) レールで本当に空のボディを返す方法?つまりコンテンツ-長さ

この記事の執筆時点では、jQuery parseJSON関数の関連部分は次のようになっています。

_parseJSON: function( data ) {
    if ( typeof data !== "string" || !data ) {
        return null;
    }

    // Make sure leading/trailing whitespace is removed (IE can't handle it)
    data = jQuery.trim( data );

    // Attempt to parse using the native JSON parser first
    if ( window.JSON && window.JSON.parse ) {
        return window.JSON.parse( data );
    }
_

ご覧のとおり、jQueryはデータが空の文字列beforeであるかどうかをテストしてトリミングしています。次に、コンソールでJSON.parse("")を実行しようとするとエラーが発生し、catchステートメントを介してajaxエラーコールバックがトリガーされます。

簡単な修正があります。 jQueryでは、1つのデータ型が要求され、別のデータ型が返されたときに、コンバーターを使用できます。詳細については、こちらをご覧ください: http://api.jquery.com/extending-ajax/

Rails head応答はテキストとしてレンダリングされるので、解析する前に応答をトリミングするjsonコンバーターへのテキストを定義するだけです。このスニペットを追加するだけです:

_// deal with Rails ' ' empty response
jQuery.ajaxSetup({
  converters: {
    "text json": function (response) {
      jQuery.parseJSON($.trim(response))
    }
  }
})
_
6
Neil Sarkar

これは、jQuery Validate Pluginの古いバージョンが原因である場合があります。このプラグインを使用している場合、この問題が発生することがあります。ケースに当てはまる場合、これを修正するアップデートがあります。

または、次のようにしてエラーハンドラーを設定することで、問題の原因を特定できます。

$.ajaxSetup()または$.ajaxError()

これはおそらく解析エラーを返します。 jQueryの新しいバージョンは、JSON解析に関して非常に厳密であることで有名です。