บทความนี้อธิบาย 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:
- วางไฟล์ที่หาเจอ (ตาม
ActiveSupport::Dependencies.autoload_paths) - 1 Class/Module ต่อ 1 ไฟล์
- ชื่อไฟล์ตามชื่อ 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 ขึ้นมาเล่นกันเถอะ
ขอบคุณที่อ่าน! 🙂