Renderowanie JSON w kontrolerze

103

Czytałem książkę i rozdział o kontrolerach, kiedy mówi o renderowaniu rzeczy, dla JSON ma taki przykład, ale nie wchodzi w szczegóły, więc nie mogłem znaleźć szerszego obrazu, do którego pasuje ten przykład:

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

A także przykład wykorzystania JSONP z funkcjami zwrotnymi:

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

Czy ktoś może to wyjaśnić?

dobroć
źródło

Odpowiedzi:

127

Zwykle będziesz zwracać JSON , ponieważ:

A) Budujesz część / całą aplikację jako aplikację jednostronicową (SPA) i potrzebujesz JavaScript po stronie klienta, aby móc pobierać dodatkowe dane bez pełnego ponownego ładowania strony.

lub

B) Budujesz interfejs API, z którego będą korzystać osoby trzecie, i zdecydowałeś się użyć JSON do serializacji danych.

Lub, być może, jesz własną dogfood i robisz jedno i drugie

W obu przypadkach render :json => some_databędzie JSON-ify podane dane. :callbackKlucz w drugim przykładzie potrzebuje nieco więcej wyjaśnienia (patrz poniżej), ale to jest inna wariacja na ten sam pomysł (powrót dane w taki sposób, że można łatwo obsługiwać JavaScript.)

Dlaczego :callback?

JSONP (drugi przykład) to sposób na obejście tej samej zasady pochodzenia, która jest częścią wbudowanych zabezpieczeń każdej przeglądarki. Jeśli masz interfejs API pod adresem api.yoursite.comi będziesz obsługiwać aplikację poza services.yoursite.comJavaScript, nie będzie (domyślnie) mógł wykonywać XMLHttpRequestżądań (XHR - aka ajax) od servicesdo api. Sposób, w jaki ludzie przekradali się przez to ograniczenie (przed sfinalizowaniem specyfikacji współdzielenia zasobów między źródłami ), polega na wysyłaniu danych JSON z serwera, tak jakby był to JavaScript zamiast JSON ). Dlatego zamiast odesłać:

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

serwer zamiast tego odeśle:

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

W ten sposób aplikacja JS po stronie klienta mogłaby utworzyć scriptznacznik wskazujący na api.yoursite.com/your/endpoint?name=Johni mieć valueOfCallbackHerefunkcję (która musiałaby być zdefiniowana w JS po stronie klienta) wywoływaną z danymi z tego innego źródła ).

Sean Vieira
źródło
i czy lepiej w ogóle nie używać tych technik i zamiast tego używać JSON-JBuilder i Eager Loading? Albo jestem zdezorientowany i to są dwie różne rzeczy.
1
@ user1899082 - te techniki są w rzeczywistości koncepcjami niższego poziomu niż te, o które będziesz się martwić, na przykład podczas korzystania z JBuilder - nie ma powodu, dla którego nie mógłbyś użyć JBuilder do ułatwienia serializacji obiektów w to_jsonmetodach - mieszanie i dopasowanie tych dwóch render :json => some_object_that_uses_JBuilder_to_render_its_jsonjest (o ile wiem) legalne.
Sean Vieira,
Dzięki Sean, twoje wyjaśnienie pomogło mi dowiedzieć się o renderowaniu json z wywołaniem zwrotnym. To rozwiązało jeden z moich problemów.
Abhi
67

Co dokładnie chcesz wiedzieć? ActiveRecord zawiera metody serializacji rekordów do formatu JSON. Na przykład, otwórz konsolę railsów i wejdź, ModelName.all.to_jsona zobaczysz wyjście JSON. render :jsonzasadniczo wywołuje to_jsoni zwraca wynik do przeglądarki z poprawnymi nagłówkami. Jest to przydatne w przypadku wywołań AJAX w JavaScript, w których chcesz zwrócić obiekty JavaScript do użycia. Dodatkowo możesz użyć callbackopcji, aby określić nazwę wywołania zwrotnego, które chcesz wywołać przez JSONP.

Na przykład, powiedzmy, że mamy Usermodel, który wygląda następująco:{name: 'Max', email:' [email protected]'}

Mamy też kontroler, który wygląda tak:

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

Teraz, jeśli wykonamy wywołanie AJAX za pomocą jQuery w następujący sposób:

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

Jak widać, udało nam się pobrać użytkownika o identyfikatorze 5 z naszej aplikacji railsowej i użyć go w naszym kodzie JavaScript, ponieważ został zwrócony jako obiekt JSON. Opcja wywołania zwrotnego po prostu wywołuje funkcję JavaScript o nazwie przekazanej z obiektem JSON jako pierwszym i jedynym argumentem.

Aby podać przykład callbackopcji, spójrz na następujące kwestie:

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

Teraz możemy utworzyć żądanie JSONP w następujący sposób:

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

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

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

Motywacją do korzystania z takiego wywołania zwrotnego jest zwykle obejście zabezpieczeń przeglądarki, które ograniczają udostępnianie zasobów między źródłami (CORS). Jednak JSONP nie jest już tak często używany, ponieważ istnieją inne techniki obchodzenia CORS, które są bezpieczniejsze i łatwiejsze.

Maks
źródło
Czy możesz trochę rozszerzyć swój przykład? Dodanie callback:opcji w rendermetodzie, a następnie pokazanie jej w Ajaxwywołaniu.
Arup Rakshit
15

Na przykład

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

Oświadczasz, że chcesz renderować @projectsjako JSON i uwzględnić skojarzenie tasksw modelu projektu w wyeksportowanych danych.

Na przykład

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

Twierdzisz, że chcesz renderować @projectsjako JSON i opakować te dane w wywołanie javascript, które będzie renderować się mniej więcej tak:

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

Umożliwia to wysyłanie danych do okna nadrzędnego i ominięcie problemów z fałszerstwami między lokacjami.

Kelly
źródło