Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

เชี่ยวชาญ Scopes ใน Ruby on Rails: คู่มือปฏิบัติจริง

Scope ใน Rails คืออะไร และทำไมถึงมีประโยชน์?

Scope คือคำสั่งสืบค้น (custom queries) ที่คุณกำหนดไว้ภายในโมเดลของ Rails โดยใช้เมธอด scope

ทุก Scope รับอาร์กิวเมนต์ 2 ค่า:

  1. ชื่อ (name) — ใช้เรียก Scope นี้ในโค้ดของคุณ
  2. ลัมบ์ดา (lambda) — ใช้สร้างคำสั่งสืบค้น

รูปแบบจะเป็นแบบนี้:

class Fruit < ApplicationRecord
  scope :with_juice, -> { where("juice > 0") }
end

เมื่อเรียกใช้ Scope คุณจะได้ออบเจ็กต์ ActiveRecord::Relation กลับมา

ซึ่งหมายความว่าคุณสามารถ เชื่อมต่อ (chain) และรวม (combine) Scopes ได้!

ตัวอย่าง:

Fruit.with_juice.with_round_shape.first(3)

ควรใช้ Scopes เมื่อไหร่?

Scopes ดีนะ แต่เราควรใช้เมื่อไหร่? มาดูตัวอย่างกัน

def index
  @books = Book.where("LENGTH(title) > 20")
end

นี่คือ Action index ใน Controller ที่ต้องการแสดงหนังสือที่ชื่อยาวกว่า 20 ตัวอักษร

เขียนแบบนี้ก็ได้ แต่ถ้าคุณต้องการใช้ Query นี้ในหลายที่ โค้ดก็จะซ้ำซ้อน

โค้ดซ้ำทำให้โปรเจกต์ยากต่อการบำรุงรักษา

มาเลื่อน Query นี้ไปใส่ใน Scope แทนกันเถอะ

เขียนแบบนี้:

class Book
  scope :with_long_title, -> { where("LENGTH(title) > 20") }
end

ตอนนี้ Controller Action จะกลายเป็น:

def index
  @books = Book.with_long_title
end

สะอาดขึ้นเยอะ!

วิธีใช้ Rails Scopes พร้อมอาร์กิวเมนต์

คุณอาจอยากส่งค่าตัวแปรเข้าไปใน Scope เพื่อให้ยืดหยุ่นขึ้น

ทำได้แบบนี้:

class Book
  scope :with_long_title, ->(length) { where("LENGTH(title) > ?", length) }
end

เครื่องหมายคำถาม (?) เป็น placeholder จะถูกแทนที่ด้วยค่าของ length ทำให้โค้ดปลอดภัยขึ้น

ถ้าอยากให้มีค่าเริ่มต้น (default value):

class Book
  scope :with_long_title, ->(length = 20) { where("LENGTH(title) > ?", length) }
end

ลองใช้ดูสิ!

Scope vs Class Method

Scopes ไม่ได้ทำอะไรลึกลับหรือพิเศษเลย — มันก็คือเมธอดธรรมดา

จริงๆ แล้ว คุณทำได้เหมือนกันด้วย Class Method:

เช่นนี้:

class Fruit
  def self.with_juice
    where("juice > 0")
  end
end

แต่ Scopes มีข้อดีด้านการออกแบบ:

  • โค้ดสะอาดกว่า เพราะ Syntax เฉพาะเจาะจง
  • Scopes ใช้ทำอย่างเดียว — ดูชื่อก็รู้ว่าเป็น Query scope
  • ไม่ได้ปนกับเมธอดอื่น ๆ ทำให้หาง่าย

ทางด้านฟังก์ชัน: ต่างกันตรงที่ Scope รับประกันว่าจะคืน ActiveRecord::Relation เสมอ ส่วน Class Method ไม่รับประกัน — ช่วยป้องกัน Error ตอน Scope คืนค่าเป็น nil

อย่าใช้ Default Scopes

Default Scope คือ Scope ที่ถูกนำไปใช้กับโมเดลโดยอัตโนมัติ

ตัวอย่าง:

class Post
  default_scope { where(published: true) }
end

ดูน่าสนใจใช่ไหม? แต่จริงๆ แล้วมันมักเป็นตัวเลือกที่ผิด เพราะคุณมักจะลืมว่ามันอยู่ ทำให้เกิด Bug แปลกๆ และเสียเวลา Debug มาก

ที่ว่านั้น...

ถ้าคุณบังคับต้องทำงานกับ Default Scope อาจต้องใช้เมธอด unscoped เพื่อปิด Scope ทั้งหมดที่กำลังทำงานอยู่

สรุป

เยี่ยมมาก! จากบทความนี้คุณเรียนรู้วิธีใช้ Rails Scopes อย่างมีประสิทธิภาพแล้ว

อย่าลืมนำไปปฏิบัติจริงเพื่อให้จดจำได้นานขึ้น

ขอบคุณที่อ่านครับ 🙂