การเชี่ยวชาญในชื่อฟังก์ชันของ Ruby
: คู่มือการกำหนดค่าตัวแปร
เมื่อทำงานกับ Ruby การตั้งชื่อและการจัดการชื่อฟังก์ชันอย่างถูกต้องเป็นสิ่งสำคัญ โดยเฉพาะอย่างยิ่งเมื่อเผชิญกับสถานการณ์ที่ท้าทายรูปแบบปกติ ปัญหาที่น่าสนใจเกิดขึ้นเมื่อพยายามตั้งค่าตัวแปรโดยใช้การเรียกฟังก์ชันที่คล้ายกับในวัตถุ ActiveRecord ซึ่งปัญหาจะหนักหนาขึ้นเมื่อคุณค้นพบว่าชื่อของตัวแปรบางตัวที่คุณต้องการมีจุดอยู่ ทำให้ซินแท็กซ์ของคุณซับซ้อนขึ้น โพสต์นี้จะชี้แจงปัญหาเสนอแนวทางระมัดระวัง และนำเสนอวิธีการที่ไม่ธรรมดาแต่มีประสิทธิภาพสำหรับโปรเจกต์ Ruby ของคุณ
ปัญหา
ในโปรเจกต์ Ruby ที่เพิ่งผ่านมา นักพัฒนาคนหนึ่งตั้งใจที่จะเขียนทับวิธี method_missing
เพื่อเปิดใช้งานวิธีการกำหนดค่าตัวแปรในลักษณะที่คล้ายกับ:
Object.variable_name = 'new value'
อย่างไรก็ตาม สถานการณ์จะซับซ้อนมากขึ้นเมื่อชื่อของตัวแปรมีจุด ตัวอย่างเช่น นักพัฒนาคนนี้พบว่าสามารถเลี่ยงปัญหานี้ได้โดยใช้:
Object.send('variable.name=', 'new value')
แม้ว่าวิธีนี้จะทำงานได้ แต่ความปรารถนาในการใช้ซินแท็กซ์ที่อ่านง่ายและสวยงามกว่าคือ:
Object.variable.name = 'new value'
ข้อควรระวัง: อย่าทำมัน!
ก่อนที่จะไปที่การทำงานรอบข้าง จำเป็นต้องเน้นถึงจุดสำคัญประการหนึ่ง: อย่าสร้างตัวระบุใน Ruby ที่ไม่ถูกต้อง! การพยายามหลีกเลี่ยงกฎเกณฑ์ของภาษาอาจทำให้เกิดโค้ดที่ไม่เชื่อถือได้และสร้างความสับสน หากคุณต้องการใช้วิธีการนี้เพื่อความชัดเจน ให้พิจารณาการใช้ attr_writer
, attr_reader
, และ attr_accessor
ที่ Ruby มีอยู่ ซึ่งถูกออกแบบมาเพื่อจุดประสงค์นี้โดยเฉพาะ ตัวอย่างเช่น:
attr_writer :bar
attr_reader :baz
attr_accessor :foo
วิธีแก้ไข: วิธีการสร้างสรรค์ด้วย method_missing
แม้จะมีข้อควรระวัง หากคุณยังคงกระตือรือร้นที่จะดำเนินการตามเส้นทางนี้ นี่คือวิธีที่คุณสามารถทำได้โดยใช้คลาสที่กำหนดเองและวิธี method_missing
จุดสำคัญที่นี่คือการคืนค่าอีกอินสแตนซ์ของคลาสเดียวกันทุกครั้งที่คุณเข้าถึงฟังก์ชัน ซึ่งจะช่วยให้คุณได้รวบรวมข้อมูลที่จำเป็นขณะนำทางผ่านการเรียกฟังก์ชันของคุณ
การ implement
นี่คือตัวอย่างการ implement แนวคิดนี้ด้วยคลาส SillySetter
:
class SillySetter
def initialize(path = nil)
@path = path
end
def method_missing(name, value = nil)
new_path = @path ? "#{@path}.#{name}" : name
if name.to_s[-1] == ?=
puts "ตั้งค่า #{new_path} #{value}"
else
return self.class.new(path = new_path)
end
end
end
s = SillySetter.new
s.foo = 5 # -> ตั้งค่า foo= 5
s.foo.bar.baz = 4 # -> ตั้งค่า foo.bar.baz= 4
การอธิบาย
- วิธี initialize: คอนสตรัคเตอร์จะเริ่มต้นตัวแปร path ที่ติดตามชื่อฟังก์ชันขณะที่มันถูกเรียกต่อเนื่อง
- method_missing: วิธีนี้จะมีไว้เพื่อแทรกการเรียกฟังก์ชันที่ไม่ได้ถูกกำหนดไว้
- หากมีการเรียกฟังก์ชันที่ลงท้ายด้วยเครื่องหมายเท่ากับ (
=
) มันจะรับรู้ว่านี่คือการตั้งค่าและแสดงค่าที่กำลังตั้งอยู่ - หากฟังก์ชันนั้นไม่สิ้นสุดด้วย
=
จะสร้างอินสแตนซ์ใหม่ของSillySetter
โดยมี path ที่ปรับปรุงแล้ว
- หากมีการเรียกฟังก์ชันที่ลงท้ายด้วยเครื่องหมายเท่ากับ (
สรุป
ใน Ruby แม้ว่าจะมีแรงดึงดูดในการเลือกเส้นทางที่ซับซ้อนในการสร้างตัวระบุที่มีจุดในชื่อ การปฏิบัตินี้สามารถนำไปสู่ความสับสนและความยุ่งยากในโค้ดของคุณ อย่างไรก็ตาม หากคุณตัดสินใจที่จะดำเนินการตามวิธีการที่ไม่ธรรมดาเช่นนี้ การ implement วิธี method_missing
ตามที่แสดงสามารถมอบความยืดหยุ่นในการตั้งค่าชื่อของตัวแปรแบบไดนามิก แม้ว่าจะมีคำเตือนที่หนักหน่วงมาพร้อมกับมัน!
เชี่ยวชาญในชื่อฟังก์ชันของคุณอย่างชาญฉลาด และขอให้คุณเขียนโค้ดอย่างมีความสุข!