Предоставление JSON в контроллере

Я читал книгу и в главе о контроллерах, когда рассказывал о вещах, для JSON у нее есть пример, подобный этому, но не вдаваясь в подробности, поэтому я не мог разобраться в увеличенной картине, что в этом примере подходит:

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

А также пример использования JSONP с функциями обратного вызова:

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

Может кто-нибудь объяснить это?

Ответ 1

Обычно вы возвращаете JSON либо потому, что:

A) Вы создаете часть/все ваше приложение как одностраничное приложение (SPA), и вам нужен ваш клиентский JavaScript, чтобы иметь возможность извлекать дополнительные данные без полной перезагрузки страницы.

или

B) Вы создаете API, который будут потреблять третьи стороны, и вы решили использовать JSON для сериализации ваших данных.

Или, возможно, вы едите свой собственный dogfood и делаете как

В обоих случаях render :json => some_data предоставит JSON-ify предоставленные данные. Клавиша :callback во втором примере нуждается в более подробном объяснении (см. Ниже), но это еще одна вариация в той же идее (возврат данных таким образом, что JavaScript может легко справиться.)

Почему :callback?

JSONP (второй пример) - это способ обойти Same Origin Policy, который является частью каждой встроенной безопасности браузера. Если у вас есть API в api.yoursite.com, и вы будете откладывать свое приложение от services.yoursite.com, ваш JavaScript не будет (по умолчанию) иметь возможность делать запросы XMLHttpRequest (XHR - aka ajax) от services до api. То, как люди пробирались вокруг этого ограничения (до того, как была завершена спецификация

вместо этого сервер отправит обратно:

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

Таким образом, клиентское JS-приложение могло бы создать тег script, указывающий на api.yoursite.com/your/endpoint?name=John, и иметь функцию valueOfCallbackHere (которая должна быть определена на стороне клиента JS), вызываемая с данными из этого другое происхождение.)

Ответ 2

Что именно вы хотите знать? ActiveRecord имеет методы, которые сериализуют записи в JSON. Например, откройте консоль рельсов и введите ModelName.all.to_json, и вы увидите вывод JSON. render :json по существу вызывает to_json и возвращает результат браузеру с правильными заголовками. Это полезно для вызовов AJAX в JavaScript, где вы хотите вернуть объекты JavaScript для использования. Кроме того, вы можете использовать опцию callback, чтобы указать имя обратного вызова, который вы хотите вызвать через JSONP.

Например, скажем, у нас есть модель User, которая выглядит так: {name: 'Max', email:' [email protected]'}

У нас также есть контроллер, который выглядит так:

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

Теперь, если мы вызываем вызов AJAX с использованием jQuery следующим образом:

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

Как вы можете видеть, нам удалось получить User с id 5 из нашего приложения rails и использовать его в нашем JavaScript-коде, потому что он был возвращен как объект JSON. Опция обратного вызова просто вызывает функцию JavaScript имени named, переданного с объектом JSON, в качестве первого и единственного аргумента.

Чтобы привести пример параметра 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, которые являются более безопасными и более легкими.

Ответ 3

Для экземпляра

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

Вы заявляете, что хотите рендерить @projects как JSON и включить в экспортированную информацию ассоциацию tasks в модели Project.

Для экземпляра

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

Вы заявляете, что хотите отобразить @projects как JSON и обернуть эти данные в javascript-вызов, который будет выглядеть примерно так:

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

Это позволяет отправлять данные в родительское окно и обходить проблемы подделки между сайтами.