JSON im Controller rendern

103

Ich habe ein Buch gelesen und in einem Kapitel über Controller, in dem es um das Rendern von Dingen geht, für JSON gibt es ein Beispiel wie dieses, aber es geht nicht auf Details ein, sodass ich das Gesamtbild, in das dieses Beispiel passt, nicht herausfinden konnte:

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

Und auch ein Beispiel mit JSONP, das es mit Rückruffunktionen verwendet:

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

Kann jemand diese erklären?

gute Kunstfertigkeit
quelle

Antworten:

127

Normalerweise geben Sie JSON zurück, weil:

A) Sie erstellen einen Teil / Ihre gesamte Anwendung als Single Page Application (SPA) und benötigen Ihr clientseitiges JavaScript, um zusätzliche Daten abrufen zu können, ohne die Seite vollständig neu zu laden.

oder

B) Sie erstellen eine API, die von Dritten verwendet wird, und Sie haben sich entschieden, JSON zum Serialisieren Ihrer Daten zu verwenden.

Oder möglicherweise essen Sie Ihr eigenes Hundefutter und tun beides

In beiden Fällen render :json => some_datawerden die bereitgestellten Daten von JSON überprüft. Der :callbackSchlüssel im zweiten Beispiel muss etwas näher erläutert werden (siehe unten), es handelt sich jedoch um eine andere Variante derselben Idee (Rückgabe von Daten auf eine Weise, die mit JavaScript problemlos verarbeitet werden kann).

Warum :callback?

JSONP (das zweite Beispiel) ist eine Möglichkeit, die Same Origin-Richtlinie zu umgehen , die Teil der integrierten Sicherheit jedes Browsers ist. Wenn Sie Ihre API unter haben api.yoursite.comund Ihre Anwendung über services.yoursite.comIhr JavaScript bereitstellen, können Sie (standardmäßig) keine XMLHttpRequest(XHR - auch bekannt als Ajax) Anfragen von servicesbis stellen api. Die Leute haben sich um diese Einschränkung herumgeschlichen (bevor die Cross-Origin Resource Sharing-Spezifikation fertiggestellt wurde ), indem sie die JSON-Daten vom Server gesendet haben, als wäre es JavaScript anstelle von JSON . Also anstatt zurückzusenden:

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

Der Server würde stattdessen zurücksenden:

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

Auf diese Weise könnte eine clientseitige JS-Anwendung ein scriptTag erstellen, auf das verweist, api.yoursite.com/your/endpoint?name=Johnund die valueOfCallbackHereFunktion (die im clientseitigen JS definiert werden müsste) mit den Daten dieses anderen Ursprungs aufgerufen werden .

Sean Vieira
quelle
und ist es besser, diese Techniken überhaupt nicht zu verwenden und stattdessen JSON-JBuilder und Eager Loading zu verwenden? Oder ich bin verwirrt und es sind zwei verschiedene Dinge.
1
@ user1899082 - Diese Techniken sind eigentlich Konzepte auf niedrigerer Ebene als das, worüber Sie sich Sorgen machen, wenn Sie beispielsweise JBuilder verwenden. Es gibt keinen Grund, warum Sie JBuilder nicht verwenden könnten, um die Serialisierung Ihrer Objekte innerhalb Ihrer to_jsonMethoden zu vereinfachen - Mischen und Das Zusammenpassen der beiden render :json => some_object_that_uses_JBuilder_to_render_its_jsonist (soweit ich das beurteilen kann) erlaubt.
Sean Vieira
Vielen Dank, Sean. Ihre Erklärung hat mir geholfen, Json mit Rückruf zu rendern. Dies hat eines meiner Probleme gelöst.
Abhi
67

Was willst du genau wissen? ActiveRecord verfügt über Methoden zum Serialisieren von Datensätzen in JSON. Öffnen Sie beispielsweise Ihre Rails-Konsole und geben ModelName.all.to_jsonSie ein, und Sie sehen die JSON-Ausgabe. render :jsonruft im Wesentlichen to_jsondas Ergebnis auf und gibt es mit den richtigen Headern an den Browser zurück. Dies ist nützlich für AJAX-Aufrufe in JavaScript, bei denen Sie JavaScript-Objekte zur Verwendung zurückgeben möchten. Darüber hinaus können Sie mit dieser callbackOption den Namen des Rückrufs angeben, den Sie über JSONP aufrufen möchten.

Nehmen wir zum Beispiel an, wir haben ein UserModell, das so aussieht:{name: 'Max', email:' [email protected]'}

Wir haben auch einen Controller, der so aussieht:

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

Wenn wir nun einen AJAX-Aufruf mit jQuery wie folgt ausführen:

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

Wie Sie sehen, haben wir es geschafft, den Benutzer mit der ID 5 aus unserer Rails-App abzurufen und in unserem JavaScript-Code zu verwenden, da er als JSON-Objekt zurückgegeben wurde. Die Rückrufoption ruft nur eine JavaScript-Funktion des Namens auf, die mit dem JSON-Objekt als erstem und einzigem Argument übergeben wurde.

callbackSehen Sie sich Folgendes an, um ein Beispiel für die Option zu geben :

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

Jetzt können wir eine JSONP-Anfrage wie folgt erstellen:

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

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

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

Die Motivation für die Verwendung eines solchen Rückrufs besteht normalerweise darin, den Browserschutz zu umgehen, der die gemeinsame Nutzung von Ressourcen zwischen Quellen (CORS) einschränkt. JSONP wird jedoch nicht mehr so ​​häufig verwendet, da andere Techniken zur Umgehung von CORS existieren, die sicherer und einfacher sind.

Max
quelle
Können Sie Ihr Beispiel etwas erweitern? Hinzufügen einer callback:Option zur renderMethode und anschließendes Anzeigen im AjaxAufruf.
Arup Rakshit
15

Zum Beispiel

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

Sie geben an, dass Sie @projectsals JSON rendern möchten , und fügen die Zuordnung taskszum Projektmodell in die exportierten Daten ein.

Zum Beispiel

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

Sie geben an, dass Sie @projectsals JSON rendern möchten , und verpacken diese Daten in einen Javascript-Aufruf, der wie folgt gerendert wird:

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

Auf diese Weise können die Daten an das übergeordnete Fenster gesendet und standortübergreifende Fälschungsprobleme umgangen werden.

Kelly
quelle