การเรนเดอร์ (Rendering) ใน Rails คืออะไร?
การเรนเดอร์เป็นเป้าหมายสูงสุดของแอปพลิเคชัน Ruby on Rails ของคุณ คุณเรนเดอร์มุมมอง (view) ซึ่งมักเป็นไฟล์ .html.erb ที่ประกอบด้วยการผสมผสานระหว่าง HTML และโค้ด Ruby
มุมมอง (View) คือสิ่งที่ผู้ใช้เห็น
มันคือผลลัพธ์ของงานทั้งหมดที่แอป Rails ต้องทำ มุมมองรวมตรรกะ ข้อมูล และเทมเพลตมุมมองเพื่อตอบสนองคำขอของผู้ใช้
การส่งคืนการตอบสนอง JSON ก็สามารถถือเป็นมุมมองได้เช่นกัน
นั่นคือเหตุผลที่ การเรียนรู้ทุกสิ่งที่เป็นไปได้ เกี่ยวกับระบบการเรนเดอร์ใน Rails จึง สำคัญ หากคุณไม่อยากให้ความพยายามทั้งหมดของคุณไปเปล่า
การเรนเดอร์ใน Rails อาจสร้างพฤติกรรมที่น่าประหลาดใจได้ ดังนั้นยิ่งคุณรู้มากเท่าไหร่ ก็ยิ่งดีเท่านั้น
มาเริ่มจากพื้นฐานกันเลย!
พื้นฐานของการเรนเดอร์มุมมอง
โดยค่าเริ่มต้น คุณไม่จำเป็นต้องบอก Rails ให้เรนเดอร์อะไรเลย และมุมมองก็ยังทำงานได้ตราบใดที่ทุกอย่างตั้งค่าถูกต้อง
นี่เป็นส่วนหนึ่งของ "Convention over Configuration" (ข้อตกลงเหนือการกำหนดค่า)
มันทำงานอย่างไร?
Rails ทำการสมมติ ซึ่งคุณอาจไม่รู้ตัว
มันช่วยประหยัดงานให้คุณ
แต่ถ้าคุณไม่รู้ว่ากำลังเกิดอะไรขึ้น มันอาจดูเหมือนเวทมนตร์
นั่นคือจุดที่คุณอาจเจอปัญหา!
ในกรณีนี้ ข้อสมมติที่ Rails ทำคือ คุณต้องการเรนเดอร์เทมเพลตที่มีชื่อเดียวกับการกระทำ (action) ของคอนโทรลเลอร์ที่กำลังจัดการคำขอ
ดังนั้น หากคุณเรียก BooksController#index... Rails จะเรนเดอร์ books/index.erb
ตอนนี้:
คุณสามารถควบคุมการเรนเดอร์ได้มากขึ้น
สิ่งนี้ช่วยให้คุณเรนเดอร์มุมมองที่ต่างจากค่าเริ่มต้นได้
วิธีทำ:
class BooksController < ApplicationController
def index
render :listing
end
end
สิ่งนี้จะเรนเดอร์ books/listing.erb (หรือ .haml หากคุณใช้ HAML views)
คุณสามารถใช้สตริงแทนสัญลักษณ์ (symbol) ได้
เช่นนี้:
render 'shared/buttons'
Rails จะเรนเดอร์ shared/buttons.erb
สิ่งหนึ่งที่คุณต้องรู้
การเรนเดอร์มุมมองที่เกี่ยวข้องกับการกระทำอื่น จะ ไม่ รันการกระทำนั้น
กล่าวคือ การเรียก render :index ภายใน create จะไม่รันเมธอด index
ทำไมจึงสำคัญ?
เพราะตัวแปรอินสแตนซ์ (instance variables) สำหรับมุมมองนั้นจะไม่ถูกตั้งค่า!
คุณต้องตั้งค่าเอง
ตัวอย่าง:
def index @users = User.all end # การขาด @users ที่นี่จะทำให้เกิดข้อผิดพลาดหรือมุมมอง index ว่างเปล่า # คุณสามารถใช้ `redirect_to` แทน ในกรณีนั้น `index` จะถูกรัน def create render :index end
เรื่องของการเรนเดอร์ยังมีอะไรให้เรียนรู้อีกเยอะ
มาต่อกันเลย!
ประเภทการเรนเดอร์ที่แตกต่างกัน
นอกจากการเรนเดอร์เทมเพลตแล้ว คุณยังมีตัวเลือกอื่นๆ
คุณสามารถ:
- เรนเดอร์สตริง HTML
- เรนเดอร์สตริงข้อความธรรมดา (plain text)
- เรนเดอร์ JSON
การเรนเดอร์สตริงอาจช่วยได้ระหว่างการพัฒนา เพื่อแสดงข้อความข้อผิดพลาดประเภทหนึ่ง หากคุณยังไม่มีเทมเพลตที่เหมาะสมสำหรับจัดการข้อผิดพลาด
หรือถ้าคุณยังไม่พร้อมเขียนมุมมองสำหรับการกระทำคอนโทรลเลอร์เฉพาะ
ตัวอย่าง:
if @user render :show else render plain: "User not found." end
การเรนเดอร์ JSON โดยตรงสามารถใช้สร้าง API เรียบง่ายได้ ไม่ใช่วิธีที่ดีที่สุดแต่ช่วยให้เริ่มต้นได้
ตัวอย่าง:
render json: @user
ผมไม่เคยใช้ render HTML แต่ถ้าคุณมีกรณีการใช้งานที่ดี แจ้งผมด้วยนะครับ!
วิธีการเรนเดอร์ Partial (พาร์เชียล)
การเรนเดอร์เกินกว่าคอนโทรลเลอร์
คุณยังสามารถ เรนเดอร์มุมมองภายในมุมมอง ได้
เราเรียกว่ามันว่า "Partial" (พาร์เชียล)
ทำไมต้องทำอย่างนั้น?
โค้ดสะอาดและนำโค้ดกลับมาใช้ซ้ำ (code reuse)
หากคุณใช้ฟอร์มเดียวกันบน 3 หน้าต่างกัน อาจเป็นไอเดียดีที่จะ แยกมันออกเป็นพาร์เชียล
ตอนนี้เมื่อคุณต้องการเปลี่ยนแปลง คุณต้องทำแค่ที่เดียว
ตัวอย่าง:
<%= render :form %>
เพื่อให้ทำงานได้ คุณต้องตั้งชื่อไฟล์มุมมองขึ้นต้นด้วยเครื่องหมาย underscore เช่น _form.erb แต่เมื่อเรียก render คุณไม่ต้องใส่ underscore
คุณจะสามารถเข้าถึง ตัวแปรอินสแตนซ์ จากพาร์เชียลได้...
แต่ตัวแปรกลาง (local variables) ล่ะ?
คุณสามารถทำได้:
<%= render :form, message: "Apples Are Good" %>
สิ่งนี้ให้คุณเข้าถึง message เป็นตัวแปรกลางในพาร์เชียลของคุณ
ต่อไป:
คุณจะได้เรียนรู้วิธีเรนเดอร์หลายสิ่งพร้อมกันด้วยการเรียก render เพียงครั้งเดียว!
วิธีการเรนเดอร์คอลเลกชัน (Collections)
พาร์เชียลช่วยให้คุณเรนเดอร์คอลเลกชันโดยไม่ต้องใช้ลูป
สมมติว่าคุณกำลังเรนเดอร์ @books
คุณสามารถทำได้:
<%= render @books %>
สิ่งนี้จะทำงานหากคุณมีพาร์เชียล _book.erb และใช้ book เป็นตัวแปรภายในเทมเพลตนั้น
ตัวอย่าง:
# app/views/books/_book.erb <%= image_tag(book.cover) %><%= book.title %>
<%= book.author %> <%= link_to "Read Book", book %>
หากคุณต้องการหมายเลขลำดับหนังสือปัจจุบัน (สำหรับคลาส CSS) คุณสามารถใช้ book_counter ได้
ที่ book_ คือชื่อโมเดลของคุณ
ผมคิดว่าการเรนเดอร์คอลเลกชันเป็นคุณสมบัติโปรดของผมใน Rails หนึ่ง!
การทำความเข้าใจ Layouts ใน Rails
เมื่อคุณสร้างแอป Rails ใหม่ จะมาพร้อมโฟลเดอร์ "layouts" ภายใต้โฟลเดอร์ views
ที่นั่นคุณจะพบไฟล์ application.html.erb
นั่นคือ layout เริ่มต้น!
Layout คืออะไร?
Layout ช่วยให้เว็บไซต์ของคุณมีลักษณะที่สอดคล้องกัน
มันคือ:
- เมนู
- ฟุตเตอร์
- การโหลดไฟล์ CSS และ Javascript...
ส่วนใหญ่ layout เริ่มต้นก็พอใช้งานได้
แต่ถ้าคุณต้องการ layout ต่างกันสำหรับหน้าต่างๆ?
คุณสามารถใช้ตัวเลือก layout ได้
ตัวอย่าง:
render :index, layout: 'admin'
คุณสามารถปิด layout ได้:
render :index, layout: false
และคุณสามารถตั้งค่า layout ที่ระดับคอนโทรลเลอร์ได้
เช่นนี้:
class AdminsController < ApplicationController layout 'admin' end
การเรนเดอร์ไม่ได้จบการทำงานของ Action
จุดสับสนที่พบบ่อยคือ การคิดว่าการเรนเดอร์ (และการ redirect) ภายในการกระทำคอนโทรลเลอร์จะหยุดการรันโค้ดที่อยู่หลังมัน
คุณอาจเจอเรื่องนี้หากคุณเรียก render หลายครั้ง
ตัวอย่าง:
def create
if yellow_fruit?
render :bananas
end
render :apples
end
สิ่งนี้จะทำให้เกิดข้อผิดพลาด เพราะ render :apples จะรันทุกครั้ง และคุณไม่สามารถเรนเดอร์สองครั้งในการกระทำคอนโทรลเลอร์เดียวกันได้
นี่คือวิธีแก้:
def create
if yellow_fruit?
render :bananas
else
render :apples
end
end
ตัวเลือกอื่นคือใช้คีย์เวิร์ด return หลัง render แต่เพื่อความชัดเจน 最好หลีกเลี่ยงคำสั่ง return กลางฟังก์ชันเมื่อเป็นไปได้
สรุป
คุณได้เรียนรู้เกี่ยวกับหัวข้อสำคัญมากของการเรนเดอร์ใน Ruby on Rails
การเรนเดอร์ช่วยให้คุณส่งคืนเนื้อหาให้ผู้ใช้แอปพลิเคชันของคุณ และเป็นหนึ่งในขั้นตอนสุดท้ายภายในการกระทำคอนโทรลเลอร์ การเข้าใจการเรนเดอร์ช่วยให้คุณเขียนแอปพลิเคชัน Rails ที่ดีขึ้น
ตอนนี้ถึงคุณแล้ว เปิดเอดิเตอร์และฝึกทักษะการเขียนโค้ดของคุณสิ
ขอบคุณที่อ่านครับ!