Friday, August 10, 2007

alias_method_chain

เมื่อวานนั่งดู source code ของ Rails
ก็ไปพบกับเจ้า method aliase_method_chain

หลักการของมัน ก็ทำนองเดียวกัย around advise ของพวก AOP
ก็คือสมมติเรามี
class Payment
def say
"hi"
end
end


ถ้าเราต้องการเปลี่ยนพฤติกรรมของมัน
เช่นต้องการเติม prefix ข้างหน้า
ก็สามารถ re-open class ได้ดังนี้
class Payment
def say_with_prefix
">> " + say_without_prefix
end

alias_method_chain :say, :prefix
end

จากข้างบน alise_method_chain จะทำการ
เปลี่ยนชื่อ method เดิมจาก "say" -> "say_without_prefix"
แล้วก็ปรับให้การเรียกใช้ "say" ไปผ่านเข้าทาง "say_with_prefix" แทน

ข้างบนลองเขียนให้สั้นๆ
แต่ pattern ใน rails ที่เขานิยมเขียนกัน
เขาจะไม่เขียนอย่างนี้
เขาจะเขียนโดยใช้ module เข้ามาช่วย
โดยตั้ง namespace ให้เป็นระเบียบ
ดังนั้นในส่วน re-open class ข้างบน เขาจะเขียนใหม่เป็นแบบนี้แทน
(Note: ชื่อ module ก็แล้วแต่จะตั้ง แต่มีกี่ชั้นก็ว่าไป)
module PAYMENT
module AROUND
def self.included(base)
base.class_eval do
alias_method_chain :say, :prefix
end
end

def say_with_prefix
">> " + say_without_prefix
end
end
end

และเมื่อไรก็ตามที่ต้องการเปลี่ยนพฤติกรรมของ class Payment ก็ให้สั่ง
Payment.send(:include, PAYMENT::AROUND)


จริงๆแล้ว alias_method_chain นั้นไม่ได้ implement อะไรใหม่เลย
มันเป็นแค่ช่วยทำให้การเขียนมันดูสื่อ และเข้าใจง่ายขึ้น
เพราะถ้าเขียนแบบ ruby ทั่วๆไปที่ไม่ใช้ alias_method_chain ก็คือต้องเขียนแบบนี้

alias_method :say_without_prefix, :say
alise_method :say, :say_with_prefix

ผมว่า aliase_method_chain ดูเข้าใจง่ายกว่านะ

Related link from Roti

No comments: