Merender JSON di pengontrol

103

Saya sedang membaca sebuah buku dan di bab tentang Pengontrol ketika berbicara tentang merender barang, untuk JSON memiliki contoh seperti ini tetapi tidak masuk ke detail sehingga saya tidak dapat menemukan gambaran yang lebih besar yang cocok dengan contoh ini:

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

Dan juga beberapa contoh dengan JSONP yang menggunakannya dengan fungsi callback:

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

Bisakah seseorang menjelaskan ini?

kebaikan
sumber

Jawaban:

127

Biasanya Anda akan mengembalikan JSON karena:

A) Anda sedang membangun sebagian / seluruh aplikasi Anda sebagai Aplikasi Halaman Tunggal (SPA) dan Anda memerlukan JavaScript sisi klien Anda untuk dapat menarik data tambahan tanpa memuat ulang halaman sepenuhnya.

atau

B) Anda sedang membangun API yang akan digunakan oleh pihak ketiga dan Anda telah memutuskan untuk menggunakan JSON untuk membuat serial data Anda.

Atau, mungkin, Anda memakan dogfood Anda sendiri dan melakukan keduanya

Dalam kedua kasus tersebut render :json => some_dataakan JSON-ify data yang diberikan. The :callbackkunci dalam contoh kedua membutuhkan lebih sedikit menjelaskan (lihat di bawah), tetapi variasi lain pada ide yang sama (kembali data dengan cara yang JavaScript dapat dengan mudah menangani.)

Kenapa :callback?

JSONP (contoh kedua) adalah cara untuk mengatasi Kebijakan Asal yang Sama yang merupakan bagian dari keamanan bawaan setiap browser. Jika Anda memiliki API di api.yoursite.comdan Anda akan melayani aplikasi Anda dari services.yoursite.comJavaScript Anda tidak akan (secara default) dapat membuat XMLHttpRequestpermintaan (XHR - alias ajax) dari serviceske api. Cara orang menyelinap di sekitar batasan itu (sebelum spesifikasi Berbagi Sumber Daya Lintas Asal diselesaikan ) adalah dengan mengirimkan data JSON dari server seolah-olah itu adalah JavaScript, bukan JSON ). Jadi, daripada mengirim kembali:

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

server malah akan mengirim kembali:

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

Jadi, aplikasi JS sisi klien dapat membuat scripttag yang mengarah ke api.yoursite.com/your/endpoint?name=Johndan memiliki valueOfCallbackHerefungsi (yang harus ditentukan di JS sisi klien) yang dipanggil dengan data dari asal lain ini .)

Sean Vieira
sumber
dan apakah lebih baik untuk tidak menggunakan teknik ini sama sekali dan menggunakan JSON-JBuilder dan Eager Loading sebagai gantinya? Atau saya bingung dan mereka adalah dua hal yang berbeda.?
1
@ user1899082 - teknik ini sebenarnya adalah konsep tingkat yang lebih rendah daripada apa yang akan Anda khawatirkan ketika Anda menggunakan JBuilder, misalnya - tidak ada alasan mengapa Anda tidak dapat menggunakan JBuilder untuk membuat serialisasi objek Anda lebih mudah di dalam to_jsonmetode Anda - pencampuran dan mencocokkan keduanya render :json => some_object_that_uses_JBuilder_to_render_its_json(sejauh yang saya tahu) sah.
Sean Vieira
Terima kasih Sean, penjelasan Anda membantu saya mengetahui tentang rendering json dengan panggilan balik, ini menyelesaikan salah satu masalah saya.
Abhi
67

Apa sebenarnya yang ingin kamu ketahui? ActiveRecord memiliki metode yang membuat catatan bersambung ke dalam JSON. Misalnya, buka konsol rel Anda dan masuk ModelName.all.to_jsondan Anda akan melihat keluaran JSON. render :jsonpada dasarnya memanggil to_jsondan mengembalikan hasilnya ke browser dengan header yang benar. Ini berguna untuk panggilan AJAX di JavaScript di mana Anda ingin mengembalikan objek JavaScript untuk digunakan. Selain itu, Anda dapat menggunakan callbackopsi untuk menentukan nama panggilan balik yang ingin Anda panggil melalui JSONP.

Misalnya, katakanlah kita memiliki Usermodel yang terlihat seperti ini:{name: 'Max', email:' [email protected]'}

Kami juga memiliki pengontrol yang terlihat seperti ini:

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

Sekarang, jika kita melakukan panggilan AJAX menggunakan jQuery seperti ini:

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

Seperti yang Anda lihat, kami berhasil mendapatkan Pengguna dengan id 5 dari aplikasi rails kami dan menggunakannya dalam kode JavaScript kami karena dikembalikan sebagai objek JSON. Opsi panggilan balik hanya memanggil fungsi JavaScript dengan nama yang diteruskan dengan objek JSON sebagai argumen pertama dan satu-satunya.

Untuk memberikan contoh callbackopsi, lihat yang berikut ini:

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

Sekarang kita dapat membuat permintaan JSONP sebagai berikut:

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

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

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

Motivasi untuk menggunakan callback seperti itu biasanya untuk menghindari perlindungan browser yang membatasi berbagi sumber daya lintas sumber (CORS). Namun, JSONP tidak banyak digunakan lagi, karena ada teknik lain untuk menghindari CORS yang lebih aman dan mudah.

Max
sumber
Bisakah Anda sedikit memperluas teladan Anda? Menambahkan callback:opsi dalam rendermetode, lalu menampilkannya di dalam Ajaxpanggilan.
Arup Rakshit
15

Misalnya

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

Anda menyatakan bahwa Anda ingin merender @projectssebagai JSON, dan menyertakan pengaitan taskspada model Proyek dalam data yang diekspor.

Misalnya

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

Anda menyatakan bahwa Anda ingin merender @projectssebagai JSON, dan menggabungkan data itu dalam panggilan javascript yang akan dirender seperti:

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

Ini memungkinkan data untuk dikirim ke jendela induk dan melewati masalah pemalsuan lintas situs.

Kelly
sumber