พอดีตอนนี้ที่ทำงานกำลังพยายามเขียน Plugin ExtJS โดยพยายามให้เป็น Convention over Configuration พยายามแทรกเข้าไปกับ model เลย ตอนนี้การสร้าง table ยังใช้การประกาศตัวแปรขึ้นมาอยู่ แต่หันไปเห็น belong_to :table, has_many :tables เลยอยากสร้าง method แบบนี้ได้บ้าง
พยายามเลียนแบบ ActiveRecord::Base อยู่พักใหญ่ แต่ได้ความว่าน่าจะใช้ self เพื่อทำให้เป็น class method แต่ก็ยังไม่สำเร็จ
class Foo
@name
def self.included(base)
base.extend(ClassMethods)
end
def x
puts @name
end
def self.y(name)
@name = name
puts "y"
end
def self.z
puts "z"
end
end
class Goo < Foo
z
y :goo
end
กว่าจะทำให้ Goo รู้จัก z ได้แทบแย่ แต่พอทดลอง
g = Goo.new
=> #
ตอนนี้เริ่มเอะใจว่าทำไมมันไม่ puts "z" แต่ก็ลองต่อไป
g.x
nil
=> nil
ที่นี้ชัดเลยว่ามันไม่ยักกะใส่ค่าให้ @name ตอนนี้เลยมืด ∞ ด้านเลยครับ
Apirak.com Panatkool
ps. ใน blognone ใช้ Module Geshi ได้หรือเปล่าครับ
เออผมลืมเรื่อง Geshi สนิทเลยแฮะ
def self.y(name)
@name = name
..
end
ตัวแปร @name ข้างบนมันอยู่ใน scope ของ Class Instance variable ซึ่งเป็นคนละ scope กับ @name ที่อยู่ใน method x
ใน class method เราไม่สามารถ access พวก instance variable ได้
วิธีทำที่ไกล้เคียงกับที่ apirak ยกตัวอย่างมาก็คือ ใช้ closure ช่วย
class Foo
def self.y(name)
define_method :x do
name
end
end
end
class Goo < Foo
y :goo
end
ตรง define method เขียนให้สั้นลงแบบนี้ก็ได้
define_method :x, lambda {name}
แอบสงสัยอย่างหนึ่งตรง self.y ใน class Foo ที่ทำให้ class Goo สามารถสั่ง
ถ้าจะทำแบบนี้ได้ y ต้องกำหนดเป็น class method อย่างเดียวเลยใช่มั้ยครับ พอดีลองไปไล่ดู Validation ใน ActiveRecord ก็เห็นพวกคลาสอย่าง validate_presence_of สร้างเป็น instance method หรือจริง ๆ แล้วเค้าเอาพวกนี้ไปประกอบกับคลาส Base ให้เป็น class method ทีหลังครับ
ลองทำโปรแกรมข้างบนให้อยู่ใน pattern เดียวกับที่ validates_presence_of ใช้ดูนะครับ
เริ่มด้วยการประกาศ module
module MyDSL
def self.included(klass)
klass.extend ClassMethods
end
module ClassMethods
def y(name)
define_method :x, lambda { name }
end
end
end
เวลาใช้
class Foo
include MyDSL
end
class Goo < Foo
y :goo
end
จริงถ้าไม่อยากเยิ่นเย้อ ก็ไป include ไว้ใน Goo ตรงๆ ก็ได้
เช่น
class Goo
include MyDSL
y :goo
end
ขอบคุณมากครับ
ตอนแรกมีสงสัยเรื่อง include / extend ด้วย แต่พอไปอ่าน Extending your include knowledge of Ruby แล้ว ก็ไขข้อข้องใจไปได้
ขอบคุณครับ :)
Apirak.com panatkool
เปิด GeSHi ให้แล้วนะครับ รายละเอียดดูใน group