3-4 วันที่ผ่านมานี้, mailing list ของ ruby กับ erlang
มีการ post announce ว่า Pragmatic Bookshelf จะออกหนังสือเล่มใหม่
เรื่อง Programming Erlang. สร้างความตื่นเต้น (วัดจาก feedback) ให้กับ mailing list ทั้งสองได้ไม่น้อย
สิ่งที่น่าสนใจก็คือ
ในกรณีนี้หัวข้อหนังสือคือ erlang
ดังนั้นไม่แปลกที่ mailing-list ของ erlang ก็ควรจะคึกครื้นเป็นธรรมดา
แล้ว่ทำไม่ mailing-list ของ ruby ถึงคึกไปด้วย
เหตุผลก็น่าจะประมาณนี้
1. Pragmatic Bookshelf หนังสือส่วนใหญ่ focus พวก ruby, rails, agile
มีกลุ่มลูกค้าชัดเจน มี brand royalty ค่อนข้างสูง
แฟนๆ ruby ก็เลยชอบไปหมด ไม่ว่าจะออกหนังสืออะไรมา
2. คนชอบ Ruby เป็นพวก "hyper-enthusiasts"
มีอะไรใหม่ๆ มันส์ๆ ก็ชอบ
สังเกตจากใน mailing list ก็มีหลายคนเขียนตอบไปว่า
มี erlang แล้ว อย่าลืมออกหนังสือ haskell ด้วยหล่ะ
ซึ่ง Pragmatic ก็ตอบไปว่า "อยากออก แต่ขั้นแรก ต้องหาคนเขียนที่เหมาะสมให้ได้ก่อน"
Wednesday, March 07, 2007
Tuesday, March 06, 2007
module_function [Ruby]
ziddik ถามเรื่องพฤติกรรมแปลกๆของ module_function
สำหรับคนที่ไม่รู้จัก module_function ลองมาดูว่ามันคืออะไรก่อน
สมมติเรา define Library math ไว้แบบนี้
ปัญหาก็คือ คนใช้ต้อง include Math ก่อน
จึงจะใช้ได้
ซึ่งดูไม่สะดวกนัก
เช่นอาจจะเกิด name conflict ได้ง่าย
module function เข้ามาช่วยในจุดนี้โดย
จะทำให้เราสามารถเรียกใช้แบบนี้ได้
ขั้นตอนภายในจะแปลกๆหน่อยตรง
1. มันจะ copy function sin เป็น instance method อันใหม่
มี code แยกออกไปจากกัน (ไม่ share กัน)
2. มันจะ mark method ให้กลายเป็น private
ส่วนคำถามว่าทำไม มันถึง mark ให้เป็น private
มีคนพยายามเดาใจ Matz เหมือนกัน
แต่ผมอ่านแล้วก็ยังไม่เข้าใจ
Re: module_functions are private?
ส่วนตัวอย่างในคำถามของ ziddik
ถ้าอยากให้ใช้ได้ ต้องเขียนเป็นแบบนี้
หรือจะ ใส่
แต่ตามที่ใน mailing list บอก
การทำเช่นนี้อาจจะเปิดโอกาสให้
shooting yourself in the foot.
Note: ผม search code ใน rails ดู
พบว่ามีการใช้ module_function อยู่นิดหน่อย
ใน package actionMailer กับ actionWebService
(ใช้อยู่นิดเดียว)
สำหรับคนที่ไม่รู้จัก module_function ลองมาดูว่ามันคืออะไรก่อน
สมมติเรา define Library math ไว้แบบนี้
module Math
def sin(x)
...
end
end
ปัญหาก็คือ คนใช้ต้อง include Math ก่อน
จึงจะใช้ได้
include Math
puts sin(10)
ซึ่งดูไม่สะดวกนัก
เช่นอาจจะเกิด name conflict ได้ง่าย
module function เข้ามาช่วยในจุดนี้โดย
module Math
def sin(x)
...
end
module_function :sin
end
จะทำให้เราสามารถเรียกใช้แบบนี้ได้
Math.sin(10)
หรือ
include Math
sin(10)
ขั้นตอนภายในจะแปลกๆหน่อยตรง
1. มันจะ copy function sin เป็น instance method อันใหม่
มี code แยกออกไปจากกัน (ไม่ share กัน)
2. มันจะ mark method ให้กลายเป็น private
ส่วนคำถามว่าทำไม มันถึง mark ให้เป็น private
มีคนพยายามเดาใจ Matz เหมือนกัน
แต่ผมอ่านแล้วก็ยังไม่เข้าใจ
Re: module_functions are private?
ส่วนตัวอย่างในคำถามของ ziddik
ถ้าอยากให้ใช้ได้ ต้องเขียนเป็นแบบนี้
module HelloModule
Version = "1.0"
def hello(name)
puts("Hello, #{name}. ")
end
module_function :hello
end
class Hello
include HelloModule
def myHello(name)
hello(name)
end
end
หรือจะ ใส่
public :hello
ใน class Hello ก็ได้แต่ตามที่ใน mailing list บอก
การทำเช่นนี้อาจจะเปิดโอกาสให้
shooting yourself in the foot.
Note: ผม search code ใน rails ดู
พบว่ามีการใช้ module_function อยู่นิดหน่อย
ใน package actionMailer กับ actionWebService
(ใช้อยู่นิดเดียว)
Related link from Roti
Labels:
ruby
Ruby 's Require ภาค 2
ปกติถ้าเราจะใช้ class อะไร
เราก็ต้อง load class นั้นขึ้นมาใน context ของเราก่อน
เช่นเรามี file
ลอง สั่ง irb
นี่คือกลไกปกติใน ruby
แต่ถ้าใครเคยใช้ rails แล้ว จะเห็นว่า
มันไม่ได้เป็นไปตาม pattern ข้างบนนี้
สมมติเรามี file
ลองสั่ง script/console ดู
คำถามก็คือ rails ไป load activity.rb มา โดยเราไม่ต้องสั่ง require สักแอะได้อย่างไร
คำตอบอยู่ใน file ที่ชื่อ
/..verylong../active_support/dependencies.rb
ภายในมี method อยู่ตัวหนึ่งที่ชื่อ
สำหรับคนที่ไม่คุ้นกับ method นี้
method นี้เป็น method ใน class
หน้าที่ method นี้ก็คือ ในกรณีที่มีการเรียกใช้ Constant ที่ไม่มีอยู่จริง
ใน dependency.rb ก็มีการ override method นี้ดังนี้
Magic ก็คือ require_dependency ที่ rails เรียกใช้
,require_dependency คือ function ที่ rails สร้างขึ้นมา
เพื่อใช้แทน require โดยมีข้อแตกต่างคือ
ในกรณีของ development environment
module, class ที่ load โดย require_dependency จะถูก
flush ออกไปหลังจากที่จบ request แล้ว
ทำให้ developer สามารถแก้ไข source code ได้อย่างสบายใจ
ไม่ต้อง restart web server ใหม่ทุกครั้งหลังจากแก้ไข code
ส่วนประโยค
ก็คือการ solve หาชื่อ file ที่จะ require
โดยมีหลักประมาณว่า
"Activity" -> 'activity'
"OrderItem" -> 'order_item'
เราก็ต้อง load class นั้นขึ้นมาใน context ของเราก่อน
เช่นเรามี file
p.rb
class Pok
def hi
"hello"
end
end
ลอง สั่ง irb
$ irb
>> Pok.new
NameError: uninitialized constant Pok
from (irb):1
>> require 'pok'
=> true
>> Pok.new
=> #<Pok:0x11158a8>
นี่คือกลไกปกติใน ruby
แต่ถ้าใครเคยใช้ rails แล้ว จะเห็นว่า
มันไม่ได้เป็นไปตาม pattern ข้างบนนี้
สมมติเรามี file
$RAILS_ROOT/app/model/activity.rb
class Activity < ActiveRecord::Base
end
ลองสั่ง script/console ดู
$ script/console
Loading development environment.
>> Activity.new
=> #<Activity:0x245efcc @new_record=true, @attributes={"name"=>nil}>
คำถามก็คือ rails ไป load activity.rb มา โดยเราไม่ต้องสั่ง require สักแอะได้อย่างไร
คำตอบอยู่ใน file ที่ชื่อ
/..verylong../active_support/dependencies.rb
ภายในมี method อยู่ตัวหนึ่งที่ชื่อ
const_missing
สำหรับคนที่ไม่คุ้นกับ method นี้
method นี้เป็น method ใน class
Module
หน้าที่ method นี้ก็คือ ในกรณีที่มีการเรียกใช้ Constant ที่ไม่มีอยู่จริง
>> class Module
>> def const_missing(name)
>> puts 'hi'
>> end
>> end
=> nil
>> Bunn
hi
=> nil
>> P
hi
=> nil
>>
ใน dependency.rb ก็มีการ override method นี้ดังนี้
class Module #:nodoc:
# Rename the original handler so we can chain it to the new one
alias :rails_original_const_missing :const_missing
# Use const_missing to autoload associations so we don't have to
# require_association when using single-table inheritance.
def const_missing(class_id)
file_name = class_id.to_s.demodulize.underscore
file_path = as_load_path.empty? ? file_name : "#{as_load_path}/#{file_name}"
begin
require_dependency(file_path)
...
long long code for error case
Magic ก็คือ require_dependency ที่ rails เรียกใช้
,require_dependency คือ function ที่ rails สร้างขึ้นมา
เพื่อใช้แทน require โดยมีข้อแตกต่างคือ
ในกรณีของ development environment
module, class ที่ load โดย require_dependency จะถูก
flush ออกไปหลังจากที่จบ request แล้ว
ทำให้ developer สามารถแก้ไข source code ได้อย่างสบายใจ
ไม่ต้อง restart web server ใหม่ทุกครั้งหลังจากแก้ไข code
ส่วนประโยค
file_name = class_id.to_s.demodulize.underscore
ก็คือการ solve หาชื่อ file ที่จะ require
โดยมีหลักประมาณว่า
"Activity" -> 'activity'
"OrderItem" -> 'order_item'
Related link from Roti
Subscribe to:
Posts (Atom)