Рендеринг JSON в контроллере

103

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

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

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

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

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

хорошее мастерство
источник

Ответы:

127

Обычно вы возвращаете JSON по одной из следующих причин :

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

или

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

Или, возможно, вы едите собачий корм и делаете и то, и другое.

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

Почему :callback?

JSONP (второй пример) - это способ обойти политику одинакового происхождения, которая является частью встроенной безопасности каждого браузера. Если у вас есть API в api.yoursite.comи вы будете обслуживать свое приложение с помощью services.yoursite.comJavaScript, то (по умолчанию) не сможете выполнять XMLHttpRequest(XHR - ajax) запросы из servicesв api. Люди обходят это ограничение (до того, как была завершена спецификация совместного использования ресурсов между источниками ), отправляя данные 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? Или я запуталась и это разные вещи.?
1
@ user1899082 - эти методы на самом деле являются концепциями более низкого уровня, чем то, о чем вы будете беспокоиться, например, при использовании JBuilder - нет причин, по которым вы не могли бы использовать JBuilder, чтобы упростить сериализацию ваших объектов внутри ваших to_jsonметодов - смешивание и совпадение этих двух render :json => some_object_that_uses_JBuilder_to_render_its_json(насколько я могу судить) законно.
Шон Виейра,
Спасибо, Шон, ваше объяснение помогло мне узнать о рендеринге json с обратным вызовом, это решило одну из моих проблем.
Abhi
67

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

Например, допустим, у нас есть Userмодель, которая выглядит так:{name: 'Max', email:' m@m.com'}

Еще у нас есть контроллер, который выглядит так:

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
    }        
});

Как видите, нам удалось получить пользователя с идентификатором 5 из нашего приложения rails и использовать его в нашем коде JavaScript, поскольку он был возвращен как объект JSON. Опция обратного вызова просто вызывает функцию JavaScript переданного имени с объектом 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, которые более безопасны и проще.

Максимум
источник
Можете ли вы немного расширить свой пример? Добавление callback:параметра в renderметод, а затем его отображение внутри Ajaxвызова.
Аруп Ракшит,
15

Например,

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

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

Например,

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

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

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

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

Келли
источник