Rendering JSON nel controller


103

Stavo leggendo un libro e in un capitolo sui controller quando si parla di rendering di cose, per JSON ha un esempio come questo ma non entra nei dettagli, quindi non sono riuscito a capire il quadro più ampio in cui si adatta questo esempio:

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

E anche qualche esempio con JSONP che lo utilizza con funzioni di callback:

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

Qualcuno può spiegarli?

Risposte:


127

Normalmente restituirai JSON perché:

A) Stai costruendo parte / tutta la tua applicazione come applicazione a pagina singola (SPA) e hai bisogno del tuo JavaScript lato client per poter inserire dati aggiuntivi senza ricaricare completamente la pagina.

o

B) Stai creando un'API che terze parti consumeranno e hai deciso di utilizzare JSON per serializzare i tuoi dati.

O, forse, stai mangiando il tuo cibo per cani e stai facendo entrambe le cose

In entrambi i casi render :json => some_dataJSON-ify i dati forniti. La :callbackchiave nel secondo esempio richiede un po 'più di spiegazione (vedi sotto), ma è un'altra variante della stessa idea (restituire dati in un modo che JavaScript può facilmente gestire).

Perché :callback?

JSONP (il secondo esempio) è un modo per aggirare la politica della stessa origine che fa parte della sicurezza integrata di ogni browser. Se hai la tua API su api.yoursite.come servirai la tua applicazione fuori dal services.yoursite.comtuo JavaScript non sarà (per impostazione predefinita) in grado di fare richieste XMLHttpRequest(XHR - aka ajax) da servicesa api. Il modo in cui le persone hanno aggirato questa limitazione (prima che la specifica Cross-Origin Resource Sharing fosse finalizzata ) è inviando i dati JSON dal server come se fosse JavaScript anziché JSON ). Quindi, invece di rimandare indietro:

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

il server invece rimanderebbe:

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

Pertanto, un'applicazione JS lato client potrebbe creare un scripttag che punta a api.yoursite.com/your/endpoint?name=Johne avere la valueOfCallbackHerefunzione (che dovrebbe essere definita nel JS lato client) chiamata con i dati da quest'altra origine .)


ed è meglio non usare affatto queste tecniche e utilizzare invece JSON-JBuilder e Eager Loading? Oppure sono confuso e sono due cose diverse.?

1
@ user1899082 - queste tecniche sono in realtà concetti di livello inferiore rispetto a ciò di cui ti preoccuperai quando usi JBuilder, ad esempio - non c'è motivo per cui non potresti usare JBuilder per rendere più semplice la serializzazione dei tuoi oggetti all'interno dei tuoi to_jsonmetodi - mescolare e l'abbinamento dei due render :json => some_object_that_uses_JBuilder_to_render_its_jsonè (per quanto ne so) lecito.
Sean Vieira

Grazie Sean, la tua spiegazione mi ha aiutato a conoscere il rendering di json con callback, questo ha risolto uno dei miei problemi.
Abhi

67

Cosa vuoi sapere esattamente? ActiveRecord dispone di metodi che serializzano i record in JSON. Ad esempio, apri la tua console di rails ed entra ModelName.all.to_jsone vedrai l'output JSON. render :jsonessenzialmente chiama to_jsone restituisce il risultato al browser con le intestazioni corrette. Ciò è utile per le chiamate AJAX in JavaScript in cui si desidera restituire gli oggetti JavaScript da utilizzare. Inoltre, puoi utilizzare l' callbackopzione per specificare il nome della richiamata che desideri chiamare tramite JSONP.

Ad esempio, diciamo di avere un Usermodello simile a questo:{name: 'Max', email:' m@m.com'}

Abbiamo anche un controller simile a questo:

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

Ora, se eseguiamo una chiamata AJAX usando jQuery in questo modo:

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

Come puoi vedere, siamo riusciti a ottenere l'utente con id 5 dalla nostra app rails e usarlo nel nostro codice JavaScript perché è stato restituito come oggetto JSON. L'opzione callback chiama solo una funzione JavaScript del nome passato con l'oggetto JSON come primo e unico argomento.

Per fornire un esempio callbackdell'opzione, dai un'occhiata a quanto segue:

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

Ora possiamo creare una richiesta JSONP come segue:

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

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

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

La motivazione per l'utilizzo di tale callback è in genere quella di aggirare le protezioni del browser che limitano la condivisione delle risorse tra le origini (CORS). Tuttavia, JSONP non viene più utilizzato molto perché esistono altre tecniche per aggirare CORS che sono più sicure e facili.


Puoi estendere un po 'il tuo esempio? Aggiunta di callback:un'opzione nel rendermetodo e quindi visualizzazione all'interno della Ajaxchiamata.
Arup Rakshit

15

Ad esempio

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

Stai affermando che desideri eseguire il rendering @projectscome JSON e includere l'associazione taskssul modello di progetto nei dati esportati.

Ad esempio

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

Stai affermando che vuoi eseguire il rendering @projectscome JSON e racchiudere quei dati in una chiamata javascript che verrà renderizzata in qualche modo come:

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

Ciò consente di inviare i dati alla finestra principale e aggirare i problemi di falsificazione tra siti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.