การแสดงผล JSON ในคอนโทรลเลอร์


103

ฉันกำลังอ่านหนังสือและในบทหนึ่งเกี่ยวกับตัวควบคุมเมื่อพูดถึงการเรนเดอร์สิ่งต่าง ๆ สำหรับ JSON มันมีตัวอย่างเช่นนี้ แต่ไม่ได้ลงรายละเอียดดังนั้นฉันจึงไม่สามารถเข้าใจภาพรวมที่ใหญ่กว่าที่ตัวอย่างนี้เหมาะ:

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

และตัวอย่างบางส่วนกับ JSONP ที่ใช้กับฟังก์ชันการโทรกลับ:

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

ใครสามารถอธิบายสิ่งเหล่านี้ได้หรือไม่?

คำตอบ:


127

โดยปกติคุณจะส่งคืนJSONเนื่องจาก:

A) คุณกำลังสร้างแอปพลิเคชันบางส่วน / ทั้งหมดของคุณเป็น Single Page Application (SPA) และคุณต้องใช้ JavaScript ฝั่งไคลเอ็นต์เพื่อให้สามารถดึงข้อมูลเพิ่มเติมได้โดยไม่ต้องโหลดหน้าซ้ำทั้งหมด

หรือ

B) คุณกำลังสร้าง API ที่บุคคลที่สามจะใช้งานและคุณได้ตัดสินใจที่จะใช้ JSON เพื่อจัดลำดับข้อมูลของคุณ

หรืออาจเป็นไปได้ว่าคุณกำลังกินการลองใช้ของตัวเองและทำทั้งสองอย่าง

ในทั้งสองกรณีrender :json => some_dataจะ JSON หากข้อมูลที่ให้มา :callbackสำคัญในตัวอย่างที่สองต้องการอธิบายอีกเล็กน้อย (ดูด้านล่าง) แต่มันเป็นรูปแบบอื่นในความคิดเดียวกัน (กลับข้อมูลในทางที่ JavaScript สามารถจัดการได้อย่างง่ายดาย.)

ทำไม :callback ?

JSONP (ตัวอย่างที่สอง) เป็นวิธีการใช้นโยบายแหล่งกำเนิดเดียวกันซึ่งเป็นส่วนหนึ่งของความปลอดภัยในตัวของเบราว์เซอร์ทุกตัว ถ้าคุณมี API ของคุณที่api.yoursite.comและคุณจะให้บริการแอพลิเคชันของคุณออกจากservices.yoursite.comJavaScript ของคุณจะไม่ (โดยค่าเริ่มต้น) จะสามารถทำให้XMLHttpRequest(XHR - อาคาอาแจ็กซ์) การร้องขอจากไป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คือใบอนุญาต (เท่าที่ฉันสามารถบอกได้)
Sean Vieira

ขอบคุณฌอนคำอธิบายของคุณช่วยให้ฉันรู้เกี่ยวกับการเรนเดอร์ json ด้วยการโทรกลับซึ่งช่วยแก้ปัญหาของฉันได้
Abhi

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 จากแอปทางรถไฟของเราและใช้ในโค้ด 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โทร
Arup Rakshit

15

สำหรับตัวอย่างของ

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

คุณระบุว่าคุณต้องการแสดงผล@projectsเป็น JSON และรวมการเชื่อมโยงtasksกับโมเดลโครงการในข้อมูลที่ส่งออก

สำหรับตัวอย่างของ

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

คุณระบุว่าคุณต้องการแสดงผล@projectsเป็น JSON และรวมข้อมูลนั้นไว้ในการเรียกใช้จาวาสคริปต์ซึ่งจะแสดงผลในลักษณะดังนี้:

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

ซึ่งทำให้สามารถส่งข้อมูลไปยังหน้าต่างหลักและข้ามปัญหาการปลอมแปลงข้ามไซต์ได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.