Wednesday, April 05, 2006

[Rails] โครงสร้างภายในของ ActiveRecord ในส่วน attributes

สมมติเรามี table products ซึ่งมี definition ดังนี้
+-------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(120) | YES | | NULL | |
| price | decimal(10,2) | YES | | NULL | |
+-------+---------------+------+-----+---------+-------+

เวลาที่เราใช้คำสั่ง find เพื่อค้นหาข้อมูล
@product = Product.find(1)

ActiveRecord จะ delegate การทำงานต่อไปยัง database adaptor ที่เรากำหนด
ซึ่ง adpater จะ fetch ข้อมูลจาก database แล้วแปลงให้อยู่ในรูป hash table
{"name"=>"test", "price"=>"11.00", "id"=>"1"}

ให้สังเกตว่า datatype จะเป็น string หมด
Note: ต้องใช้ debugger เข้าไป step ดู จึงจะเห็น, ถ้าใช้วิีธี print debug
โดยเรียกใช้ method attributes จะเห็นเป็น datatype ที่
activerecord ทำการ convert ให้แล้ว


จากนั้น finder ก็จะทำการ new Model Object ขึ้นมา
และกำหนด instance variable @attributes
ให้มีค่าเท่ากับ hash result ที่ได้จาก database adaptor

การ access object attribute ปกติเราจะใช้คำสั่งแบบนี้

old_price = @product.price
@product.price = 12

ในครั้งแรกที่เราเรียกใช้ method price หรือ price=
method พวกนี้จะยังไม่มีอยู่จริง
แต่ Activerecord จะใช้ method method_missing ดักไว้
(method_missing เป็นกลไกของ ruby ที่ไว้ support กรณี send message ไปยัง method ที่ไม่ได้ define ไว้)
และทำการ manipulate ค่าใน @attributes โดยใช้ method
read_attribute กับ write_attribute
Note: method read_attribute, write_attribute
มีคุณสมบัติพิเศษ ก็คือ มันช่วยในการ convert datatype ให้ด้วย
ถ้าเราเรียกใช้ @product.read_attribute('price')
ผลลัพท์ที่ได้กลับมา จะอยู่ในรูปของ Float value

หลังจากนั้น activerecord ก็จะ check ว่า flag generate_read_methods
เป็น true หรือไม่ ถ้าใช่ มันก็จะทำการ generate method ให้เราอัตโนมัติ
ซึ่งมีผลให้การ access ครั้งต่อไปมี performance ที่ดีขึ้น

เวลาที่เรานำ activerecord model ไปใช้งานร่วมกับ UI layer
ค่าที่ pass มาจาก form เรามักจะกำหนดให้อยู่ในรูป hash table
ผลที่ได้ ก็คือเราสามารถนำ hashtable นั้น มา update model
ของเราได้โดยตรง (เพราะ internal structure ของ model
ก็เป็น hash เหมือนกัน)

Related link from Roti

No comments: