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

คุณควรใช้ขอบเขตหรือวิธีการเรียนหรือไม่?

บทความนี้มีในภาษาเกาหลีด้วย ขอบคุณ Soonsang Hong!

ขอบเขตเป็นวิธีที่ยอดเยี่ยมในการดึงวัตถุที่ถูกต้องออกจากฐานข้อมูลของคุณ:

app/models/review.rb
class Review < ActiveRecord::Base
  scope :most_recent, -> (limit) { order("created_at desc").limit(limit) }
end

คุณจะใช้ขอบเขตดังนี้:

app/models/homepage_controller.rb
@recent_reviews = Review.most_recent(5)

การเรียกขอบเขตนั้นดู ตรง เหมือนเรียก class method ใน Review . และง่ายต่อการสร้างเป็นวิธีการของชั้นเรียนแทน:

app/models/review.rb
def self.most_recent(limit)
  order("created_at desc").limit(limit)
end
app/controllers/homepage_controller.rb
@recent_reviews = Review.most_recent(5)

แล้วทำไมคุณถึงใช้ขอบเขตในเมื่อคุณสามารถใช้วิธีคลาส Ruby ปกติได้ มันคุ้มค่าไหมที่จะแยกแนวคิดเหล่านี้ออกจากกันโดยสิ้นเชิง แต่เทียบเท่ากับแนวคิดในหัวของคุณ? เกิดอะไรขึ้นถ้าคุณพบข้อบกพร่องแปลก ๆ สิ่งพิเศษทั้งหมดนี้เป็นสิ่งที่ทำให้ Rails เรียนรู้ได้ยากขึ้นใช่หรือไม่

เมื่อ จะ ควรใช้ขอบเขตแทนวิธีการเรียนหรือไม่

เหตุใดจึงต้องใช้ขอบเขตในเมื่อเรามีเมธอดของคลาสอยู่แล้ว

จะเป็นอย่างไรถ้าคุณต้องการคว้าบทวิจารณ์ทั้งหมดที่เขียนขึ้นหลังจากวันที่ระบุ แต่ถ้าไม่ได้ระบุวันที่ คุณต้องการ ทั้งหมด ความคิดเห็นกลับมาแทน?

ขอบเขตจะมีลักษณะดังนี้:

app/models/review.rb
scope :created_since, ->(time) { where("reviews.created_at > ?", time) if time.present? }

ง่ายพอใช่มั้ย? แล้ววิธีการเรียนล่ะ

app/models/review.rb
def self.created_since(time)
  if time.present?
    where("reviews.created_at > ?", time)
  else
    all
  end
end

ต้องใช้การทำงานพิเศษเล็กน้อย ขอบเขตต้องการส่งคืนขอบเขต ดังนั้นจึงเชื่อมโยงเข้าด้วยกันได้ง่าย:

Review.positive.created_since(5.days.ago)

แต่เพื่อให้วิธีการเรียนทำงานในลักษณะเดียวกัน คุณต้องจัดการกรณีที่เวลาเป็นศูนย์โดยเฉพาะ มิฉะนั้น ผู้โทร จะต้องค้นหาว่ามีขอบเขตที่ถูกต้องและเชื่อมโยงได้

วิธีการที่ส่งคืนวัตถุประเภทเดียวกันเสมอนั้นมีประโยชน์จริงๆ . คุณไม่ต้องกังวลกับเคสขอบหรือข้อผิดพลาดมากนัก คุณสามารถสมมติได้ว่าคุณจะได้รับสิ่งของที่สามารถใช้ได้คืนเสมอ

ในที่นี้หมายความว่าคุณสามารถเชื่อมโยงขอบเขตเข้าด้วยกันโดยไม่ต้องกังวลว่า nil คุณค่ากลับมา

ยังมีวิธีที่คุณสามารถทำลายสมมติฐานที่ว่าคุณจะได้ขอบเขตกลับมาเสมอ:

app/models/review.rb
scope :broken, -> { "Hello!!!" }
irb(main):001:0> Review.broken.most_recent(5)
NoMethodError: undefined method `most_recent' for "Hello!!!":String

แต่ฉันไม่เคยมีสิ่งนั้นเกิดขึ้นในโค้ดจริง

สิ่งที่ฉันชอบมากที่สุดเกี่ยวกับขอบเขตคือมันแสดงความตั้งใจ . คุณกำลังบอกคนต่อไปที่อ่านโค้ดของคุณว่า "วิธีนี้สามารถผูกมัดได้ ในที่สุดจะกลายเป็นรายการของวัตถุ และจะช่วยคุณเลือกชุดของวัตถุที่เหมาะสม" นั่นเป็นมากกว่าวิธีการเรียนทั่วไปทั้งหมด

เมื่อใดที่คุณควรใช้วิธีคลาสแทนขอบเขต

เนื่องจากขอบเขตแสดงเจตจำนง ฉันจึงใช้ขอบเขตเหล่านี้ทุกครั้งที่ผูกมัดขอบเขตที่เรียบง่ายและมีอยู่ในตัว (เช่น where และ limit ) ในขอบเขตที่ซับซ้อนยิ่งขึ้น . การค้นหากลุ่มวัตถุที่เหมาะสมคือสิ่งที่กำหนดขอบเขตไว้

มีข้อยกเว้นสองประการ:

  1. เมื่อฉันต้องการโหลดขอบเขตล่วงหน้า ฉันจะเปลี่ยนเป็นการเชื่อมโยงแทน .
  2. เมื่อฉันทำมากกว่าการโยงขอบเขตในตัวไปยังขอบเขตที่ใหญ่ขึ้น ฉันใช้เมธอดของคลาส .

เมื่อลอจิกขอบเขตของคุณมีความซับซ้อน วิธีการเรียนจะรู้สึกเหมือนเป็นสถานที่ที่เหมาะสม

ภายในวิธีการเรียน คุณสามารถผสมรหัส Ruby กับรหัสฐานข้อมูลได้อย่างง่ายดาย หากคุณมีรหัสการจัดเรียงที่เขียนใน Ruby ได้ง่ายกว่า คุณสามารถคว้าอ็อบเจ็กต์ของคุณในลำดับเริ่มต้น และใช้ sort_by เพื่อจัดลำดับให้ถูกต้อง

หรือหากคุณรู้สึกยุ่งยากเป็นพิเศษ วิธีการของคลาสสามารถดึงข้อมูลจากที่ต่างๆ ได้ เช่น ฐานข้อมูลของคุณ Redis หรือ API หรือบริการภายนอก จากนั้นจึงนำมารวมกันเป็นคอลเลกชั่นของวัตถุที่ รู้สึก เหมือนขอบเขตที่ถูกเปลี่ยนเป็นอาร์เรย์

ถึงอย่างนั้น ก็ยังดีที่จะใส่การเลือก การจัดเรียง การเข้าร่วม และการกรองโค้ดไว้ในขอบเขต จากนั้น ใช้ขอบเขตของคุณภายในวิธีการเรียนของคุณ คุณจะลงเอยด้วยวิธีการเรียนที่ชัดเจนขึ้นและขอบเขตที่คุณใช้ได้ทั่วทั้งแอป

ขอบเขตเป็นหนึ่งในคุณสมบัติ Rails ที่ฉันโปรดปราน คุณสามารถทำสิ่งที่ทรงพลังได้ อ่านบทความของฉันเกี่ยวกับการจัดเรียงและกรองโมเดล Rails เพื่อดูตัวอย่างขอบเขตที่มีประโยชน์อย่างยิ่ง

และมีวิธีง่ายๆ ในการควบคุมขอบเขตด้วยการใช้ขอบเขต:เล่นกับมันภายในแอปขนาดเล็กที่เน้น บทตัวอย่างฟรีของ Practicing Rails จะแสดงให้คุณเห็นวิธีการ ลองดูสิ!