Надання JSON в контролері


103

Я читав книгу і в розділі про контролери, коли мова йде про рендеринг матеріалів, для JSON є такий приклад, але не вникає в деталі, тому я не міг з'ясувати більшу картину, до якої цей приклад підходить:

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

А також деякі приклади з JSONP, що використовує його з функціями зворотного виклику:

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

Хтось може це пояснити?

Відповіді:


127

Ви зазвичай повертаєте JSON або тому, що:

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

або

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

Або, можливо, ви їсте власну собачу їжу і робите і те, і інше

В обох випадках render :json => some_dataJSON-ify надає дані. :callbackКлюч у другому прикладі потрібно трохи більше пояснення (див нижче), але це ще одна варіація на ту ж ідею (повернення даних таким чином , що JavaScript може легко обробляти.)

Чому :callback?

JSONP (другий приклад) - це спосіб обійти ту саму політику оригіналу, яка є частиною вбудованої безпеки кожного браузера. Якщо у Вас є свій API на api.yoursite.comі ви будете служити вашої програми з services.yoursite.comвашого JavaScript НЕ буде (за замовчуванням) бути в змозі зробити 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 з зворотним викликом, це вирішило одну з моїх проблем.
Абхі

67

Що саме ви хочете знати? ActiveRecord має методи, які серіалізують записи в JSON. Наприклад, відкрийте консоль рейки та введіть, 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
    }        
});

Як бачите, нам вдалося отримати Користувача з id 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 вже не використовується так багато, оскільки існують інші методи обходу, які є безпечнішими та простішими.


Чи можете ви трохи розширити свій приклад? Додавання callback:параметра в renderметоді, а потім показ його всередині Ajaxвиклику.
Arup Rakshit

15

Для прикладу

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

Ви заявляєте, що хочете відобразити @projectsяк JSON, та включаєте об'єднання tasksдо моделі Project у експортовані дані.

Для прикладу

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

Ви заявляєте, що хочете відобразити @projectsяк JSON, і загортаєте ці дані у виклик javascript, який буде виглядати приблизно так:

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

Це дозволяє надсилати дані до батьківського вікна та обійти проблеми підробки між веб-сайтами.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.