Friday, March 02, 2007

Ruby 'require'

คำสั่งง่ายๆคำสั่งหนึ่งที่หลายคน (รวมผมด้วย) มองข้ามไปก็คือ require
คำว่ามองข้าม หมายถึง ใช้พอเป็น, แต่่ไม่สนใจกลไกของมัน
ถ้ามีปัญหาก็มั่วอย่างเดียว จนกว่าจะใช้ได้

วันนี้ก็เลยนั่งสะสาง ความเข้าใจเกี่ยวกับเจ้า require

require คือกลไกการ include source code อย่างหนึ่งของ ruby
มีคำสั่งที่เหมือนกันอีกคำสั่งหนึ่งก็คือ load
สิ่งที่ต่างกันก็คือ ถ้าสั่ง require ซ้ำๆกัน
มันจะ load แค่ครั้งแรกครั้งเดียว

ลองสร้าง file p.rb ที่ current directory
a = 1
b = 2
@c = 3
def d
"hi"
end

จากนั้นก็เรียก irb แล้วสั่ง
$ irb
>> require 'p'
=> true
>> require 'p' # load ครั้งที่ 2 return false เพราะถือว่า load ไปแล้ว
=> false

เงื่อนไขอย่างหนึ่งของการ require ก็คือ
local variable ที่อยู่ใน p.rb จะไม่ตามมาด้วย
>> require 'p'
=> true
>> a
NameError: undefined local variable or method `a' for #
from (irb):3
>> b
NameError: undefined local variable or method `b' for #
from (irb):4
>> @c
=> 3
>> d
=> "hi"


คำถามถัดมาก็คือ แล้วเวลาสั่ง require 'p'
มันมองหา file ที่ชื่อ p.rb ที่ไหนบ้าง,
ruby มีตัวแปร array อยู่ตัวหนึ่งที่ชื่อ $LOAD_PATH
ซึ่งตัวแปรนี้มี short-name อีกชื่อหนึ่งคือ $:
(คนไม่ชอบ perl เห็นแล้วคงร้องยี้)
>> $LOAD_PATH
=> ["/usr/local/lib/ruby/gems/1.8/gems/wirble-0.1.2/bin",
"/usr/local/lib/ruby/gems/1.8/gems/wirble-0.1.2/.",
"/usr/local/lib/ruby/site_ruby/1.8",
"/usr/local/lib/ruby/site_ruby/1.8/powerpc-darwin8.7.0",
"/usr/local/lib/ruby/site_ruby", "/usr/local/lib/ruby/1.8",
"/usr/local/lib/ruby/1.8/powerpc-darwin8.7.0", "."]
>> $:
=> ["/usr/local/lib/ruby/gems/1.8/gems/wirble-0.1.2/bin",
"/usr/local/lib/ruby/gems/1.8/gems/wirble-0.1.2/.",
"/usr/local/lib/ruby/site_ruby/1.8",
"/usr/local/lib/ruby/site_ruby/1.8/powerpc-darwin8.7.0",
"/usr/local/lib/ruby/site_ruby",
"/usr/local/lib/ruby/1.8",
"/usr/local/lib/ruby/1.8/powerpc-darwin8.7.0", "."]
>>

ดังนั้นถ้าเราอยาก add load path ส่วนตัวของเรา
เราก็สามารถ append path เข้าไปใน ตัวแปรนี้ได้เลย
>> $LOAD_PATH << '/tmp' 


ที่นี้ลองไปดูที่ rails บ้าง
rails เตรียม custom configuration ให้เรา set load_path
ไว้ใน file $RAILS_ROOT/config/environment.rb
Rails::Initializer.run do |config|
config.load_paths += %W( #{RAILS_ROOT}/extras )
end

การทำงานภายใน ก็คือมันไปเรียกใช้ตัวแปร $LOAD_PATH
แต่แทนที่จะ append ไปข้างหลัง $LOAD_PATH array
มันใช้วิธีไส่ไว้ข้างหน้าแทน เพราะกลไกการหามันจะเริ่มจาก
หน้าไปหลัง การใส่ไว้ข้างหน้า ทำให้สามารถ override file ข้างหลังได้
# Set the <tt>$LOAD_PATH</tt> based on the value of
# Configuration#load_paths. Duplicates are removed.
def set_load_path
configuration.load_paths.reverse.each { |dir| $LOAD_PATH.unshift(dir) if File.directory?(dir) }
$LOAD_PATH.uniq!
end

Related link from Roti

Thursday, March 01, 2007

Linux บน Mainframe

ปกติเห็นใครใช้ Linux ก็จะดีใจ
เพราะเห็นว่ามันออกไปในแนวทางพึ่งตนเองดี

แต่วันนี้ได้ยินข่าวนี้แล้วก็รู้สึกแปลกๆ
(แปลก ตรงว่า ไม่ค่อยเชื่อใจว่าจะใช้งานได้คุ้ม ตามราคาที่จ่ายไป)

สัญญา สปส. 2900 ล้านที่เซ็นไป เขาเริ่มทำงานแล้ว (ใครจะหาว่าสัญญามีกลิ่นตุๆ ก็ว่ากันไป)
โดยมีการยก mainframe เข้าไปติดตั้ง
เพื่อพร้อมที่จะทำการขึ้นระบบแรก
mainframe ที่ว่านี้จะมีแต่ linux ล้วนๆ
โดยทำเป็น virtual machine
ซึ่งคาดเดาว่าจะช่วยลด cost ที่ต้องมี server กระจัดกระจายได้
+ share กันไช้ cpu ทำให้รวมๆแล้วมีจำนวน cpu ที่ต้องใช้ลดลง

เมื่อมี hardware ก็ต้องมี software
ระบบแรกที่จะส่งมอบ phase แรก
ก็คือระบบ "ประชาสัมพันธ์ข่าวสารกระทรวง"
ว้าว ระบบนี้มีบุญจริงๆ ได้ run บน mainframe ด้วย

เอ้ามองโลกแง่ดีหน่อย
มีเวลา 5 ปี ที่จะหาระบบดีๆ ขึ้นไป run
เพื่อให้คุ้มกับค่างบ 2900 ล้าน

Related link from Roti