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

เชี่ยวชาญ Zeitwerk: คู่มือเชี่ยวชาญ Module Autoloading ใน Ruby

บทความนี้อธิบาย Class และ Module Autoloading ใน Ruby รวมถึง Gem ใหม่ "Zeitwerk" ที่มาพร้อม Rails 6

เริ่มจากคำถาม...

เรารวม Multiple Source Files ให้กลายเป็นหนึ่งยังไง? — require พวกมัน

Require ทำให้ Ruby อ่านไฟล์และรันโค้ด — แตถ้ามี Required Files เยอะ อาจไม่ต้องโหลดทั้งหมด ทันที

อย่างน้อยไม่ใช่ตอนนี้... โหลดไฟล์ เฉพาะตอนต้องการ ให้ App เริ่มเร็วขึ้นได้ยังไง?

นั่นคือ Autoloading!

วิธีใช้ Autoloading

Ruby มี Built-in Autoloading — Based on Constants

ตอน Constant เช่น Coconut ถูกพบครั้งแรก Ruby จะพยายามโหลดไฟล์ที่เกี่ยวข้อง

แตก่อนหน้านั้น: ต้อง Register Constant นี้กับชื่อไฟล์ก่อน

แบบนี้:

 autoload :Coconut, "lib/coconut.rb" 

ตอนนี้ Ruby รู้ว่าต้องไปหาที่ไหนตอนใช้ Class/Module Coconut

แต่มันจะดีกว่านี้ไหม? จินตนาการว่าไม่ต้อง Register Constants ด้วยมือ และ Ruby รู้ทุกอย่างอยู่แล้ว

นั่นคือสิ่งที่ Rails ทำ — แต่ก่อน Rails 6 มันไม่ได้ใช้ Mechanism autoload

Autoloading ใน Rails ก่อน Rails 6

ไม่เข้าใจเต็มที่ว่ามันทำงานยังไง แต Rails ใช้ const_missing แทน autoload เพื่อ Auto-find และ Load Files

ทำไมมีประโยชน์? เพราะไม่ต้อง require ในโปรเจกต์ Rails — Convention over Configuration...

ทุกอย่าง Auto ตาม Rules:

  1. วางไฟล์ที่หาเจอ (ตาม ActiveSupport::Dependencies.autoload_paths)
  2. 1 Class/Module ต่อ 1 ไฟล์
  3. ชื่อไฟล์ตามชื่อ Class ใช้ Underscore (UsersController => users_controller)

ตอนโค้ดอ้างอิง Class Names ใดๆ Rails จะรู้หาเจอ — มากประโยชน์

Autoloading ใน Rails หลัง Rails 6

Rails 6 Introduce Constant Autoloading ใหม่ — ชื่อ Zeitwerk

ต่างจาก "Classic" Rails Autoloading ยังไง?

Classic ใช้ const_missing ขาด Info เช่น Module Nesting — มี Limitations เยอะ

Zeitwerk ใช้ Ruby's autoload — Implementation ใหม่นี้ Follow File-naming Conventions คล้ายเดิม

จริงๆ แล้ว: Zeitwerk ใช้ Filename 推断 (Infer) Class Name — users_controller => UsersController — ตรงข้ามกับก่อนหน้า

Btw ยังใช้ autoload_paths ได้ แตควรเพิ่ม BASE paths เท่านั้น เช่น "/lib" แทน "/lib/**"

ทำไม? เพราะ Namespaces และ Nesting

  • ถ้า "lib" อยู่ใน autoload อยากสร้าง "Fruit::Orange" ไฟล์ต้องเป็น "lib/fruit/orange.rb"
  • แต่ถ้า "lib/fruit" อยู่ใน autoload ต้องโฟลเดอร์อีกชั้น ไฟล์กลายเป็น "lib/fruit/fruit/orange.rb" สำหรับ Class เดียวกัน

จุดดีที่สุด? ฟังก์ชันใหม่นี้ไม่ติดกับ Rails — ใช้ใน Non-Rails Projects ได้!

Summary (สรุป)

คุณเรียนรู้ Module Autoloading ใน Ruby — คืออะไร ทำงานยังไง!

ด้วยความเข้าใจใหม่นี้ คุณโครงสร้าง Ruby Projects ได้อย่างมีประสิทธิภาพที่สุด

ถึงคุณแล้ว — เปิด Editor ขึ้นมาเล่นกันเถอะ

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