コントローラでのJSONのレンダリング


103

本を読んでいて、レンダリングに関する話をするときにコントローラーについての章で説明しました。JSONの場合、次のような例はありますが、詳細には立ち入っていません。

render :json => @projects, :include => tasks

また、JSONPをコールバック関数で使用するいくつかの例:

render :json => @record, :callback => 'updateRecordDisplay'

誰かがこれらを説明できますか?

回答:


127

通常は、次のいずれかの理由でJSONを返します

A)アプリケーションの一部/すべてを単一ページアプリケーション(SPA)として構築していて、ページを完全に再読み込みせずにクライアント側のJavaScriptで追加のデータを取得できる必要があります。

または

B)サードパーティが消費するAPIを構築していて、JSONを使用してデータをシリアル化することにしました。

または、おそらく、あなたは自分のドッグフードを食べて両方をしている

どちらの場合もrender :json => some_data、提供されたデータをJSON化します。:callback2番目の例のキーはもう少し説明する必要があります(以下を参照)が、これは同じアイデアの別のバリエーションです(JavaScriptが簡単に処理できる方法でデータを返す)。

なんで:callback

JSONP(2番目の例)は、すべてのブラウザーの組み込みセキュリティーの一部である同一生成元ポリシーを回避する方法です。あなたがであなたのAPIを使用している場合api.yoursite.com、あなたはのオフに、あなたのアプリケーションを提供しますservices.yoursite.comあなたのJavaScript(デフォルトで)行うことはできませんXMLHttpRequestからのリクエスト- (別名AJAX XHR)servicesにしますapi。(Cross-Origin Resource Sharing仕様が確定する前に)人々がこの制限をこっそりとこなしてきた方法は、JSON ではなくJavaScriptであるかのようにサーバーからJSONデータを送信することです)。したがって、送り返すのではなく、

{"name": "John", "age": 45}

代わりにサーバーが送り返します。

valueOfCallbackHere({"name": "John", "age": 45})

したがって、クライアント側のJSアプリケーションは、この別のオリジンからのデータで呼び出されるscriptタグを作成し、api.yoursite.com/your/endpoint?name=JohnそのvalueOfCallbackHere関数(クライアント側のJSで定義する必要があります)を呼び出すことができます


そして、これらのテクニックをまったく使用せず、代わりにJSON-JBuilderとEager Loadingを使用する方が良いでしょうか?または私は混乱していて、それらは2つの異なるものです。

1
@ user1899082-これらの手法は、JBuilderを使用するときに心配するよりも実際には低レベルの概念です。たとえば、JBuilderを使用してto_jsonメソッド内でオブジェクトを簡単にシリアライズできなかった理由はありません。2つを一致させることrender :json => some_object_that_uses_JBuilder_to_render_its_jsonは(私が知る限り)正当です。
Sean Vieira

Seanに感謝します。あなたの説明は、コールバックを使用したjsonのレンダリングについて知るのに役立ちました。これは私の問題の1つを解決しました。
Abhi 2014年

67

正確に何を知りたいですか?ActiveRecordには、レコードをJSONにシリアル化するメソッドがあります。たとえば、railsコンソールを開いて入力するModelName.all.to_jsonと、JSON出力が表示されます。render :json基本的にto_json、正しいヘッダーを使用して結果を呼び出し、ブラウザに返します。これは、使用するJavaScriptオブジェクトを返すJavaScriptでのAJAX呼び出しに役立ちます。さらに、このcallbackオプションを使用して、JSONP経由で呼び出すコールバックの名前を指定できます。

たとえばUser、次のようなモデルがあるとします。{name: 'Max', email:' m@m.com'}

次のようなコントローラーもあります。

class UsersController < ApplicationController
    def show
        @user = User.find(params[:id])
        render json: @user
    end
end

ここで、次のようにjQueryを使用してAJAX呼び出しを行うと、

$.ajax({
    type: "GET",
    url: "/users/5",
    dataType: "json",
    success: function(data){
        alert(data.name) // Will alert Max
    }        
});

ご覧のとおり、ids 5のユーザーをrailsアプリから取得し、JSONオブジェクトとして返されたため、JavaScriptコードで使用することができました。コールバックオプションは、JSONオブジェクトを最初の唯一の引数として渡された名前付きのJavaScript関数を呼び出すだけです。

callbackオプションの例を示すには、以下を見てください。

class UsersController < ApplicationController
    def show
        @user = User.find(params[:id])
        render json: @user, callback: "testFunction"
    end
end

これで、次のようにJSONPリクエストを作成できます。

function testFunction(data) {
    alert(data.name); // Will alert Max
};

var script = document.createElement("script");
script.src = "/users/5";

document.getElementsByTagName("head")[0].appendChild(script);

このようなコールバックを使用する動機は、通常、クロスオリジンリソースシェアリング(CORS)を制限するブラウザー保護を回避することです。ただし、JSONPはそれほど使用されていません。なぜなら、CORSを回避するために、より安全で簡単な他の手法が存在するからです。


あなたの例を少し拡張できますか?メソッドにcallback:オプションを追加し、renderそれをAjax呼び出し内に表示します。
Arup Rakshit

15

インスタンスの場合

render :json => @projects, :include => :tasks

@projectsJSONとしてレンダリングtasksし、エクスポートされたデータにプロジェクトモデルの関連付けを含めることを指定しています。

インスタンスの場合

render :json => @projects, :callback => 'updateRecordDisplay'

@projectsJSONとしてレンダリングし、そのデータをjavascript呼び出しでラップして、次のようにレンダリングしたいと述べています。

updateRecordDisplay({'projects' => []})

これにより、データを親ウィンドウに送信し、サイト間の偽造問題を回避できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.