11/29/2006

Agile Web Development with Rails 第二版


Ruby on Rails 界的聖經 Agile Web Development with Rails 的第二版終於脫離 Beta ,開始送印了。所有購買 PDF Version 的人應該都會收到一封信
The final version of Agile Web Development with Rails went to the printer last Friday. This means that the paper book will start shipping sometime around December 15.
然後所有購買 PDF 版本的人都已經拿到最新的 PDF 了吧 XD 。我想距離 Amazon 上面買到應該不遠,大概是12月中就可以開始訂購了。這本書一定要敗的啦!!!

11/28/2006

敝公司出了大事,萬事都得延宕下來

基本上,我肯待一家公司,代表我對他有忠誠,我喜歡或是認同這間公司的作風 。這次我們公司處於生死存亡之際,我恐怕沒太多時間寫 Blog ,本 Blog 在最近更新可能非常緩慢,請原諒,我想跟我的公司一同度過這個難關。

BTW ,看到這一長串討論文章,以及Hemidemi聲援的網友,我看到了德不孤,必有鄰這句話。

Comet on Lighttpd

Comet 果然是開始慢慢發酵,Lighty 作者 Jan 也開始對 Comet 有興趣了
Can I use it ?
Not yet. This is a idea how to implement COMET in a nice, performing fashion. On the way to 1.5.0 it will be implemented. Meanwhile I’m looking for comments on the idea and if it matches your needs for COMET and AJAX.
他還沒決定怎麼作,不過可以確定的是事情是他會在 1.5 上面 implement ,implement 方式可能是採用 mod_multiplex 或是 mod_mailbox 方式來作。

至於 Comet 可以拿來作的東西,AJAX 也都做得到。但是有些程式的架構本身就比較適合 Server Push ,而不適合 Polling。像是聊天室,IM等程式都是廣泛的 Comet 應用,期待 Lighty on Comet 的到來。

11/27/2006

What's new in Rail 1.2's ActiveRecord

Rails 1.2 RC 出了,我們也該好好看看多了什麼有趣的東西。基於我認為 Active Record 是 Rails 的核心價值,所以我先從 Active Record 開始說起。就如我剛剛說的 Active Record 是 Rails 的核心價值,在企業中,核心價值是很難允許修改的,所以這次的改版對於 Active Record 修改非常少 XD 我發現幾個比較重要的改變。

  1. Condition find 變得更加 Rails
    原本還很 SQL Like 的 Condition find
    Person.find(:all, :conditions => [ "last_name = ? and status = ?", "Catlin", 1 ])
    變成
    Person.find(:all, :conditions => { :last_name => "Catlin", :status => 1 })
  2. Has_through 更加好用
    支援 :uniq => true , << , delete ,改天嘗試看看能不能取代 has_and_belongs_to_many
  3. Has_one support dependent
    一共有
    :destroy, :delete, and :nullify 幾個 option
基本上在 Active Record 端修改的不多,不過光是 condition find 跟 has_through 的進步就值得我們更新到 Rails 1.2。

11/23/2006

Rails 1.2 RC 1 出了

雖然手邊的工作正在趕上線,但是這個新聞太大了,還是得報一報,Rails 1.2 RC 1出了。 賣點如下
  • REST REST REST !!!
  • response_to : 別人給你一個request,你可以選擇回應的 format,像是 HTML ,XML,RSS之類的。
  • Auto-Loading Lib
  • MultiByte:你沒看錯,Unicode Support
  • Route 改版
  • ProtoType :Prototype’s Ajax-based forms no longer serialize disabled form elements
  • Action Mailer 加強:MIME 1.0 Default
詳細情況看這裡吧。要嘗鮮的人請按
gem install rails --source http://gems.rubyonrails.org --include-dependencies
這次 1.2 版最主要進步就是 REST,讓 Ruby on Rails 繼續往更加前瞻性的 Web Framework 邁進。恭喜 Rails Team!!!

update : 有關於 Restful 的介紹,請看

Something really close

最近一周 Blog 都沒時間寫,實在很汗顏。因為 Ruby on Rails 的專案即將上線,這周的每天都在 tune performance ,修改Bug,寫文件,還有找出頁面忘記加入那些連結。最近的感覺就跟馬拉松要最後衝刺的心情一樣
『快成功了,不過還差一點』
到目前為止,程式研發時間大概是 2.5 個月 * 2 人。但是扣掉Partner 是學生,一周大概只有 2 人天,我一周上班時間本來就大概 3~4 人天,9~11 月之間我還配合公司行銷專案,隨手開發了 2 ~ 3個小專案。(因為這些案子我都用用 Ruby on Rails ,我才能『隨手』開發 =.=)所以總開發時間大概是 2 ~ 2.5 人月比較正確。

身為 Ruby on Rails 推廣者,我總是會被問到『國內有那些公司用 Ruby on Rails?』。雖然我花很多時間寫文件 。不過到最後發現,比起寫一百篇文章,推廣的效果還不如自己寫一個網站所帶來的效益來得高,也比較有說服力。LAMP 獲得尊敬也是等到 Wikipedia,Flickr,Digg 等網站規模起來了,才獲得商業公司廣泛的肯定以及採用。這個案子如果真的可以起來,相信會給國內 Ruby on Rails 界一個大大的振奮。

這個案子結束後,我該思考兵役的問題了~~~

PS. 最近壓力測試發現 Mongrel 真的很穩。

11/22/2006

HTML Filter 3: XSS

講了那麼多 HTML Filter 的例子 例子2,回到一個問題?如果照著之前的程式,有沒有辦法防範 XSS ?我現在給的答案是
不容易
為什麼?難道 Rails 那麼爛?錯了,看看這個表吧,當你的站遇到 Extra dot for absolute DNS 這種攻擊。
<IMG """><SCRIPT>alert("XSS")</SCRIPT>">
我們發現,有太多玩法可以放 XSS,而濾掉特定 tag 方式幾乎行不通,因為我們還是希望開放某些有用的 tag 像是 a 或是 img。但是我們可以減少這種可能發生率
  1. 使用 white list filter ,盡量少用 black list,whitelist 就是僅僅開放某些 tag ,blacklist 就是僅僅關閉某些 tag。我之前的 html filter 就是 white list 的。
  2. href 跟 src 裡面要檢查 javascript 的欄位
  3. 如果沒必要開放 tag ,盡量使用 h 通殺
延伸閱讀
  1. XSS 筆記
  2. XSS 列表

11/18/2006

Linux Journal Editor's Choice of 2006


Linux Journal 12月份選出了 Editor Choice of 2006 。 如大家預料的,2005~2006保持無敵狀態的 Ruby on Rails 1.1.6 當選了 Web Framework of 2006。另外一個喜訊是Ruby 1.8.5 當選了 Programming Language of 2006,主要原因是 JRuby 受到 SUN 的青睞,打敗了入選者 Object-C 跟 Python。

另外一些跟本Blog有關的獎項,Apache 2.2 打敗了 Lighttpd ,成為 Web Server of 2006。Postgresql 8.2 打敗了 MySQl 跟 SQLite 成為了 Database Server of 2006。

媽,我上 iThome 了~~

台灣 Ruby 社群接受 iThome 記者採訪,並且在 269期(2006/11/18~11/24)獲選為封面故事『搜索Ruby on Rails的高速魔法』。看完全部的章節之後,發現我講的話有點多 XD
Update: 訪談線上版已經上線了

11/17/2006

為什麼 Debian 跟 Ubuntu 上面沒有 ruby-gems?

Ruby Gems 是一個相當重要的 Ruby 套件管理系統,有太多 Ruby and Rails 的 Plugin 在 Gems 上面可以方便的下載。但是,FreeBSD ,MAC OS X,Gentoo 都可以直接用預設的套件系統安裝 gems ,卻只有標榜安裝快速方便的 Debian 跟 Ubuntu 沒有提供 APT 安裝。這到底是為什麼呢?

我看了一些討論串這裡網頁解釋了許多 Debian 上面為何不加入 Ruby Gems 的原因。
  • Rubygems packages are not compatible with the FHS. Rubygems follows the “one directory per package and version” rule.
  • It is not possible to do “normal” (FHS-compatible) installations of rubygems, and some ruby software developers have started to distribute their software as gems only.
  • Rubygems is source-intrusive. The require instruction is replaced by a require_gem instruction to allow for versioned dependencies. Debian and most other systems think that dealing with versioned dependencies outside of the source is a better idea.
  • There are currently no plans to improve RubyGems to ease the work of Debian and RPM packagers.
當然啦,每個套件系統都有自己的 concern,不過我不太能接受這個理由,難道 Ruby Gems 必須為了特定系統開發一個新的方式嗎?

到底是系統應該配合開發者的習性,還是開發者得自己去適應系統的規則?

但是看到這個網頁,我覺得這個講的比較實在點
Pure ruby gems are converted fine. However, ones including C extensions are not.
大意是如果這個 GEMS 是純 Ruby 當然歡迎,但是有些 Ruby Gems 是有 C extenstions 的(一些 Ruby Lib 像是 ruby-mysql ),那就很容易出現安裝錯誤,所以相當不建議使用 Ruby Gems 摟。 為此,Debian-Ruby 的 Daigo Moriwaki 也寫了自動轉換 GEM 成為 DEB 的程式,希望能方便大家打包 Ruby Gems 的 DEB Package。但是話說回來, Ruby Gems 那麼多,你怎麼可能全部包成 DEB ?Ruby GEMS上有些東西有安全性顧慮時,要緊急下載 patch ,這時通常官方會建議使用 Gem 去更新,難道 DEB 也可以立刻做到即時更新?還是要使用者自己苦哈哈下載 source 自己裝?

到底是系統應該配合開發者的習性,還是開發者得自己去適應系統的規則?

如果答案是後者的話,Ruby GEMS 要怎麼做到跨平台?所以 Daigo Moriwaki 也深知這個道理,也提供了 Unofficial 的 deb source XD
deb http://www.sgtpepper.net/hyspro/deb unstable/
deb-src http://www.sgtpepper.net/hyspro/deb unstable/
Update 完 DEB index 之後,apt-get install rubygems 即可。

11/16/2006

Applet in Ruby

Tr Ruby 是我第一個發現 AJAX 可怕之處的 Demo site,你可以在 Web 上面打入任何 ruby command,他也會立刻顯示 irb 的結果。JRuby 作者在自己 Blog 提出了一篇Ruby for the Web? Check,裡面有一個嚇死人的 Demo ,形式跟 Tr Ruby 是一樣的,但是唯一不同的是,他不是用 AJAX,而是用 Applet 去跑的,要看demo 請到這裡觀賞

Yes, JRuby can run in an applet. No, it's not that hard. No, the archive doesn't have to be this big (the applet above is about a 1.6MB JAR file, but it includes stuff it doesn't need). Yes, this means you could start writing stuff for web pages in Ruby. No, I'm not kidding.

作者也興奮的莫名其妙,我也興奮的莫名其妙!!!JRuby 自從 SUN 接管後,實在突飛猛進呀。

HTML Fliter Part(2):yml 化的 sanitize

根據上一篇 HTML Filter ,我們發現到這個 sanitize 很好用。但是,但是,他的 okTags 太醜了,我不喜歡。
def sanitize( html, okTags='a href, b, br, i, p' )
我在想,能不能更加的 Ruby 化一點,所以我就花了點時間改寫一下程式,變成了新版的 sanitize。我們將 allow 的 tag 跟 attribute 寫在 yml 裡面,然後執行時 load 進去,這樣似乎比較結構化一點,並且可以在 Rails 使用。License 是 MIT。

首先,你先寫一個 allow_tags.yml 的 file ,原本 okTags = 'a href target, b, br, p, i' 變成了
a:
- href
- target
b:
br:
p:
i:
a: 代表你接受 a 這個 tag ,後面加上 -href 代表你接受 a tag 底下的 href attribute ,如果你還要加一個 target attribute 就是加一個 -target ,不難懂吧。

如果你在 Ruby on Rails 裡面,建議放在 config 下面。然後,將這段程式(nopaste 版本)放到任何可以 loading 的地方即可。

HTML Filter

一般來說,通常使用者 input 的 field 都會作一些 filter 的動作,避免你塞一些危險的 HTML code (script之類)進去。而這部份 Ruby on Rails 作法很簡單,就是在前面加上一個 h() 即可。h 在Ruby on Rails 作什麼事情呢?他是 html_escape 的 alias ,他會將所有的 < 還有 > 變成 & lt; ,& gt;,比如 <sctipt>alert('a'); </sctipt> 會變成
& lt;sctipt& gt;alert('a'); & lt;/sctipt& gt;
這樣你就完全作不了亂啦,因為所有 tag 都不見了。但是這樣通常嫌太過嚴格一點了,有時候我們會希望開放一些字型大小,顏色的tag 給你用,這時候 h() 通殺的特性會讓一切都變得很麻煩。所以這時候 Ruby on Rails 就出現 sanitize() 這個 function,根據 Ruby on Rails 的api 上面解釋
Sanitizes the given HTML by making form and script tags into regular text, and removing all "onxxx" attributes (so that arbitrary Javascript cannot be executed). Also removes href attributes that start with "javascript:".
他會砍掉 script 這個 tag ,以及 onClick onLoad 之類的 attribute ,你沒有機會執行 javascript ,那就會讓你 key-in 任何東西都如 sanitize 字面上一樣『完全無害』。但是,Ruby on Rails 預設的 sanitize 管制方式又有點大方,你還是可以塞一些 div 或是 iframe 之類的 tag 讓你的網站版面爛掉。

所以我們需要一個可以自訂的 HTML Filter ,可以自由指定我們放行那些 tag 。這時候我發現了這個網頁,這是 Brad Choate's 寫的 perl 函式 sanitize_html 的 Ruby porting,你可以到這裡下載 Ruby 的版本。這只有一個函式,請將這個函式放在任何可以 loading 的地方,然後使用
sanitize( HTML 程式碼 )
即可。我們來仔細研究一下怎麼使用,他的第一行
def sanitize( html, okTags='a href, b, br, i, p' )
okTags 代表的意思是就是他允許的 tag ,目前有 a ,b , br , i , p 之類的 tag 。如果你輸入 <iframe>aaa</iframe>之類的不允許的 code ,他會出現
aaa
這樣的結果,所有不被允許的 tag 一律被濾掉。如果你想加入 span,font 這個兩個 tag ,那就將他變成
def sanitize( html, okTags='a href, b, br, i, p, span, font' )
以此類推,很簡單吧。至於第一個的 a href 代表什麼意思呢?第一個 a 代表 sanitize 允許 a 這個 tag ,第二個 href 跟第一個 a 中間沒有逗號分開,代表 sanitize 允許 a 這個 tag 使用 href 這個 attribute。你要是不信的話,打入 <a href="http://lightyror.blogspot.com" target="_blank">Haha</a>之類的程式,他只會出現
<a href="http://lightyror.blogspot.com">Haha</a>
只有 href 這個 attribute 會被保留,其他的刪無赦 XD。如果你想讓 a 這個 tag 加入 target attribute ,那麼就這樣寫吧。
def sanitize( html, okTags='a href target, b, br, i, p' )
如此他就會保留 href 跟 target 這兩個 attribute。最後,當我們輸入這樣的 HTML <a href="http://lightyror.blogspot.com">Haha 有頭無尾的 html code ,神奇的是他居然會補齊 tag 成
<a href="http://lightyror.blogspot.com">Haha</a>
恩,這個東西實做相當完整,看起來十分有用。

11/12/2006

Lighttpd 1.5 + Linux Async IO

出自Lighttpd 的作者 Jan 發表的 Benchmark,發現到當使用 Lighttpd 1.5(還在 trunk 階段)裡面最新的 Linux Async IO ,不管是小 file benchmark ,還是大 file benchmark,會有將近 80% 的效能進步
1.5.0 will be a big win for all users. It will be more flexible in the handling and will have huge improvement for static files thanks to async io.
為什麼會有那麼大的進步,其實我不清楚細節,畢竟我本身對這方面沒有研究,不過根據 GSlin的說法
async I/O 將 read request 丟給 kernel 後先去做其他事情,等到 kernel 處理完以後再用 callback routine 告訴 lighttpd 已經完成讀取。這使得 kernel 可以最佳化讀取的順序以達成 I/O 效率的提升,另外一方面 lighttpd 也可以趁機去做其他的事情。
會讓原本Lighttpd就很強勢的 static file handling 有跳躍式的 performance 進步。至於 Lighttpd 1.5 何時會出呢?因為 Jan 在 MySQL AB 工作(我剛知道也蠻驚訝的),而目前他正在忙
At MySQL we are in the final strokes of getting a GA release of Monitoring and Advisoring Service of MySQL Enterprise out of the door.
所以還得稍微等等。Lighttpd 1.5 會加入萬眾期待的 mod_proxy_core 以及現在這個 Linux Async IO,實在是相當的令人期待。

Update:Jan 已經丟出最新的 Lighttpd 1.5 Pre-release

IBM 使用 Ruby on Rails 來開發 Koala Project

Koala Project 是一個紀錄,分享商業流程的 Project 。他有提供 Wiki 跟 Firefox 的 slider bar。其實這些都不太重要,重點是那是 Ruby on Rails 寫的!!!
IBM is using Ruby on Rails in efforts such as its Koala project, which involves development of a wikipedia-like system for business processes.
IBM 另外一個 Web 2.0 計畫 Fringe,他們不確定是否要使用 Ruby on Rails 。

在這篇報導的另外一個重點是,IBM 不保證會幫 Ruby on Rails 出像 Eclipse 這樣的 IDE XD。
But the company thus far has made no commitments to releasing any development tools for the Ruby on Rails crowd, said Steve Cousins, senior manager for IBM's User-Focused Systems Research Group at the San Jose site.
但是不保證並不代表否認,大家等著看吧 XD。

眾所皆知 IBM 投入 Java 投入的很深,甚至還 release Eclipse 這種重量級的 IDE 給大家玩。而最近 Java 界跟 Scripting Language 走得很近,也開始探尋 Scripting Language + Java 的可能玩法。所以這或許是IBM想直接試試看 Ruby on Rails 的能耐,加碼 Ruby on Rails 。或許也只是 IBM 對 Java + Ruby 的探路。總之,越來越多大公司開始加碼 Ruby on Rails ,這是實情。至於 Ruby on Rails IDE 的部份,個人感覺是 IBM 可能會直接加碼 Rad Rails 比較快。

11/11/2006

Tim Bary 看 Rails,PHP,Java

台灣Ruby論壇發現的,Anw跟Contagion總是可以找到一些我沒注意到的新聞@@!。Sun 的 XML 標準製作者 Tim Bary 發表他對 Rails,PHP,Java 的看法。出乎意料的,在 Sun 自家人的眼裡 Java 並沒有佔了上風。
Rails 贏在開發時間,跟後續的維護,可擴充性被認為最差(雖然我不認為Rails Scaling 很差)。PHP贏在可擴充性,但是後續維護被評為最差。Java 在開發工具上勝利,但是開發速度自己人都覺得不夠好。他的 Slides 可以在這裡 Download

他的評比項目包括
  • Scaling:Load balancing,Shared-nothing,CPU ,DBMS,File I/O,Observability
  • 開發時間:Compilation step?,Deployment step? ,Code Size ,Configuration process
  • 開發工具:IDE,Templating,How many tools?,O/R Mapping ,Performance , Documentation
  • 後續維護:MVC,Object orientation ,Readability ,Language count ,Code size

本篇圖片來自這個網頁,所有權屬於 Sun and Tim Bary,有問題請告知。

11/10/2006

Rails 的單複數轉換怎麼實做的呢?

很多人看到 Ruby on Rails 的單複數轉換,就覺得很神奇,怎麼可能會有那麼聰明的機制可以作到。別以為 Ruby on Rails 那麼神,還內建英漢字典 XD 根據這篇的說法,其實這只是一個小技巧,作法看這篇下面的程式碼。他絕對不只看字尾是 y 還是 s 去作判斷,而是有一個小小的詞庫判斷字尾以及特殊字。雖然這無法做到全部單字單複數轉換,不過其實也差不多了,再多作也沒啥太大意義。

另外,如果對於單數數搞不清楚,可以使用 ruby script/console 裡面打 pluralize 跟 singularize 來測試一下
>> puts 'cat'.pluralize
cats
>> puts 'people'.singularize
person



Rails 的單複數轉換

1. Inflector.inflections do inflect

2. inflect.plural(/$/, 's')

3. inflect.plural(/s$/i, 's')

4. inflect.plural(/(axtest)is$/i, '\1es')

5. inflect.plural(/(octopvir)us$/i, '\1i')

6. inflect.plural(/(aliasstatus)$/i, '\1es')

7. inflect.plural(/(bu)s$/i, '\1ses')

8. inflect.plural(/(buffaltomat)o$/i, '\1oes')

9. inflect.plural(/([ti])um$/i, '\1a')

10. inflect.plural(/sis$/i, 'ses')

11. inflect.plural(/(?:([^f])fe([lr])f)$/i, '\1\2ves')

12. inflect.plural(/(hive)$/i, '\1s')

13. inflect.plural(/([^aeiouy]qu)y$/i, '\1ies')

14. inflect.plural(/(xchsssh)$/i, '\1es')

15. inflect.plural(/(matrvertind)ixex$/i, '\1ices')

16. inflect.plural(/([ml])ouse$/i, '\1ice')

17. inflect.plural(/^(ox)$/i, '\1en')

18. inflect.plural(/(quiz)$/i, '\1zes')

19.

20. inflect.singular(/s$/i, '')

21. inflect.singular(/(n)ews$/i, '\1ews')

22. inflect.singular(/([ti])a$/i, '\1um')

23. inflect.singular(/((a)naly(b)a(d)iagno(p)arenthe(p)rogno(s)ynop(t)he)ses$/i, '\1\2sis')

24. inflect.singular(/(^analy)ses$/i, '\1sis')

25. inflect.singular(/([^f])ves$/i, '\1fe')

26. inflect.singular(/(hive)s$/i, '\1')

27. inflect.singular(/(tive)s$/i, '\1')

28. inflect.singular(/([lr])ves$/i, '\1f')

29. inflect.singular(/([^aeiouy]qu)ies$/i, '\1y')

30. inflect.singular(/(s)eries$/i, '\1eries')

31. inflect.singular(/(m)ovies$/i, '\1ovie')

32. inflect.singular(/(xchsssh)es$/i, '\1')

33. inflect.singular(/([ml])ice$/i, '\1ouse')

34. inflect.singular(/(bus)es$/i, '\1')

35. inflect.singular(/(o)es$/i, '\1')

36. inflect.singular(/(shoe)s$/i, '\1')

37. inflect.singular(/(crisaxtest)es$/i, '\1is')

38. inflect.singular(/(octopvir)i$/i, '\1us')

39. inflect.singular(/(aliasstatus)es$/i, '\1')

40. inflect.singular(/^(ox)en/i, '\1')

41. inflect.singular(/(vertind)ices$/i, '\1ex')

42. inflect.singular(/(matr)ices$/i, '\1ix')

43. inflect.singular(/(quiz)zes$/i, '\1')

44.

45. inflect.irregular('person', 'people')

46. inflect.irregular('man', 'men')

47. inflect.irregular('child', 'children')

48. inflect.irregular('sex', 'sexes')

49. inflect.irregular('move', 'moves')

50.

51. inflect.uncountable(%w(equipment information rice money species series fish sheep))

52. end

11/09/2006

從 Django 看 Ruby on Rails 成功的原因

這裡有一份對岸 cookoo 寫的对Django的遗憾,真是一篇好文章,裡面描寫到 Django 如何錯失大鳴大放的機會。我看完之後,突然發現 cookoo 這篇文章藉由 Django 的缺點,他也順便偷偷分析了 Ruby on Rails 成功的原因。大家可以來看看

  1. django的原始碼改動頻繁
  2. ORM API 繁瑣(後來按ActiveRecord風格重寫)
  3. 没有整合的測試框架
  4. 沒出書,文件相比Rails缺之甚多
  5. python內部有人對django完全獨立的一套full-stack系统有不同看法,又搞了很多别的框架(比如turbogears)
  6. django對AJAX熱潮無動於衷
相比起來

  1. Rails Team 相當穩定,很少大改
  2. ORM 太優美了
  3. 出的書籍一級棒,文件也相當多
  4. Ruby 因為社群小,超級團結
  5. Full Stack 框架,Unit Test 內建
  6. RJS 趕上 AJAX 熱潮,炒熱不少話題
雖然 Open Source 技術為本,但是撇開 Ruby on Rails 優秀的技術不談。
  • 假如大家都不寫文件,Ruby on Rails 的文件不夠多的話,有人敢用一個不熟悉的語言嗎?
  • 沒有將 Ruby 社群主力放在 Rails 身上,寫得出那麼多 API 嗎?
  • 沒有團結的團隊,人員來來去去,吵來吵去的團隊作得出好作品嗎?
  • 沒有 DHH 肯花寫程式以外的時間推銷 Rails ,並且花眾多時間寫出一本Agile Web Development with Rails,會更多人願意花時間去學習一個聽都沒聽過,也沒有公司support 的 Ruby on Rails 嗎?

一向是一盤散沙的 Open Source 社群可以仔細思考一下 Ruby on Rails 帶給大家的啟示。Ruby 社群向心力強,不分散力量,又懂得出書以及掌握時勢用RJS炒熱話題。這說明,團隊管理好,向心力強,行銷強,正是 Ruby on Rails 擴散那麼快速的主因。其實,這不正是一個好商業團隊應該具備的特質嗎?

Pagination Collection:進階版的分頁

當我第一眼看到 Pagination 時,我感覺到他是一個很好的東西 ,但是第二眼(大概十分鐘後)就覺得這東西很『實用嗎?』,雖然我很喜歡 Ruby on Rails ,但是我依然覺得預設的 Pagination 這個東西是一個基本版的功能。Let's face the music。
如果我們要加入一些關聯性的資料庫操作時,要怎麼分頁?
是在後面加入 :conditions 的敘述嗎?但是如果跨relation tables使用呢?當我開始質疑 Ruby on Rails 在分頁實做不夠的時候,Ruby 跳出來了。

根據 Wiki,請在任何 controller 可以 load 的地方加入這一行程式
def paginate_collection(collection, options = {})
default_options = {:per_page => 10, :page => 1}
options = default_options.merge options

pages = Paginator.new self, collection.size, options[:per_page], options[:page]
first = pages.current.offset
last = [first + options[:per_page], collection.size].min
slice = collection[first...last]
return [pages, slice]
end
然後,將你可以使用任何 Active Record 裡面 Model 的函式,不管是預設的還是你自己寫的,只要可以取出 Model Collection 的函式,都可以套入以下的方式
@分頁Object ,  @object_list = paginate_collection (
隨便一個Model.任何可以取出collection的函式,
:page => @params[:page] )
然後其他 View 的使用方式就跟原本的 Pagination 一模一樣,完全沒有變。這時候有人會問,什麼都可以套入 paginate_collection 嗎?

是的。

假設 blogs 跟 comments 呈現 1 : m 的關係,而你想對特定一個 blog 的 model 底下的 comment 作分頁,你可以使用
@pages ,  @comment_list = paginate_collection (
blog.comments, :page => @params[:page] )
這還不夠,我有一個特別為某個 a Model 撰寫的函式 find_hotest,這個函式會先去把某個 1:m 關係底下的所有 model object 取出來,然後每個 model object 都去找出另外一個相對應 n : m 的 Model 的數量取出來並且作 sort 。你看不懂我在講什麼沒關係,你只要知道這個在底層實做,這是一個我怎麼算都要 5個 SQL 做出來的函式,相當複雜。(不過我用 Active Record 1 行就寫出來了,Active Record 真是太神奇了)當我想要為這個可怕的函式作分頁,當然不可能使用 paginate :condition 來寫,但是我們可以使用 paginate_collection
@pages ,  @a_list = paginate_collection (
a.find_hotest ,
:
page => @params[:page] )
一樣可以做到分頁,而且 view 使用完全一模一樣。只要能夠套到 Active Record ,我想這個 paginate_collection 就應該趨近於無敵,可以陪伴我左右,替我東征西討做完許多任務。

Beyond Java 裡面 Justin Gehtland 說的一段話
最近,Ruby 動態的特性真的為我帶來許多好處。我的應用系統需要一些常用的功能,這些功能應該歸屬於框架層次。不需要深入原碼,來加上這些新功能。我就只是在執行期動態的擴充我需要的類別。這種擴充性是許多靜態型別語言所詛咒的(且不會這麼做的)
我想,這個例子是這段話的最好的佐證。當我每次覺得 Ruby on Rails 缺乏那個功能時,Ruby 總是會跳出來說『這個交給Ruby 去作,可以很簡單就做出來』。Ruby on Rails 將心力花在他所注重的事情上面,其他不足的東西,就交給 Ruby 去作吧。以前我覺得是『 Ruby on Rails 造就了 Ruby』,現在我覺得『Ruby on Rails 跟 Ruby 處於水幫魚,魚幫水的角色,誰都少不了誰』。

Ruby 很美,Rails 很神奇,但是少了其中一個,另外一個就不再閃閃發光。只有兩者並行,才足以撼動世界。

11/08/2006

Pagination :讓分頁不再繁瑣

Ruby on Rails 其中一個特色,就是把 Web Programming 裡面繁瑣的細節,用優美簡單的語法來修飾。所以,通常你不需要花太多時間在細節上面,而是可以直接往 business logic 進攻。什麼是繁瑣的細節呢?分頁就是典型的例子。

什麼是分頁呢?舉 Google 為例子,
約有7,020項符合rails的查詢結果,以下是第 21-30項。

這些就是分頁,商業邏輯超級簡單,但是出現頻率也超級高,繁瑣到不能再繁瑣的東西。這個時候 Rails用 Paginaton 來解救苦難的同胞啦。Pagination 顧名思義,Google 字典是這樣解釋的
pagination: 分頁; 標記頁數
不過一直到今天,我才知道分頁的英文(汗)。果然學 Ruby on Rails 讓我英文進步不少(尤其是一些單複數的英文),可以考慮當作一個學 Rails 的優點 XD 。他是一個 Build in 的功能,所以他整合的很好,我們從 controller level 跟 action level 來看。

Action Level:

單一個 action 才會使用到的分頁,使用方式如這
 def list
@person_pages, @people =
paginate :people
end
他 會都會去 people 資料庫撈全部的資料,然後將取出來的值放在 @people 這個變數裡面,另外他會寫入分頁檔案到 @person_pages 這個變數裡面,至於現在的頁數他會放到 params[:page] 這個變數裡面。至於排序,限制一頁有幾個資料等等的問題,他都有選項可以設定,請看Pagination手冊

Controller Level :

代表全部的 action 都要分頁
class PersonController < ApplicationController
paginate :people
end
他會每個 action 都會去作剛剛的事情。每一個 action 都會去 people 資料庫撈全部的資料,然後將取出來的值放在 @people 這個變數裡面,另外他會寫入分頁檔案到 @person_pages 這個變數裡面,至於現在的頁數他會放到 params[:page] 這個變數裡面。

View 寫法:

寫好 controller 當然要開始進入重點了,View 要怎麼用?我們看看剛剛指定完成的變數, @people ,跟 @person_pages 。首先,@people 代表的是 Model Object 的 array ,使用方式大家很清楚。但是 @person_pages 代表的是分頁這個 Object ,這就有點意思了,我們來看看怎麼用。

  1. 所有的數量: @person_pages.item_count
  2. 目前這一頁的第一個序號@person_pages.current.first_item
  3. 目前這一頁的最後一個序號@person_pages.current.last_item
  4. 上一頁: link_to(h('< page =""> @person_pages.current.previous}) if @person_pages.current.previous
  5. 下一頁:link_to(h('Next >'), {:page => @person_pages.current.next}) if @person_pages.current.next
  6. 頁數列表(就是 1 2 3 4 5 6):pagination_links(@person_pages
簡單吧!!! Pagination 使用就是那麼簡單,而且可以幫你簡單的避開繁瑣的分頁,真是很實用的東西。

效率問題

你們可能會懷疑,到底 pagination 在資料量大時,會不會很耗記憶體呢?答案是不會。我們從 SQL 來看這個作法。當你的 pagination 的寫法是
@user_pages, @users = paginate ( :users, :per_page => 5 )
那麼相對應 SQL code 是
SELECT count(*) AS count_all FROM users
SELECT * FROM users LIMIT 0, 5
也就是說,pagination在『全部資料筆數』的擷取是用 count(*) 來作。而『頁面列表的部份』,這個例子是每個頁面只show五筆,他在SQL裡面有加入 LIMIT 0 , 5 這個東西。對我來說,這在 SQL 中已經是最佳解法了,我們並沒有取出所有用不到的資料,所以在 pagination 在取出資料表的部份不會有資料量太大的問題:)。

延伸閱讀:
  1. Rails Wiki about Pagination
  2. Pagination Manual

大公司對於 Ruby and Ruby on Rails 的動作列表

國際大廠對於新技術的動作一向保守,不過這一年來,他們對於 Ruby and Ruby on Rails 的動作從觀望,似乎變成了開始小幅買進了。

  1. SUN:Sun 僱用了 JRuby 核心開發者NetBeans可以寫Ruby 了
  2. Amazon:Amazon疑似加碼 37 Signal ? , UnSpun : Amazon 開始使用 Rails
  3. Yahoo: Yahoo Developer Network 也開始加入 Ruby 選項
  4. Microsoft:MS 聘了 RubyCLR 創造者M$對 Ruby 非常有興趣的報導
  5. Google: Google 買下用 Ruby on Rails 寫的Measure Map 。這家公司也擁有 Rails Core Team 其中一員Nicholas Seckar。
  6. IBM:IBM採用 Ruby on Rails 來開發 Koala Project
  7. Dell:Dell Idea Strom 也用 Ruby on Rails
藉由一連串的 Ruby 大爆發以及 Ruby 書籍銷售長紅,大家或多或少都看到 Ruby and Ruby on Rails 的能力跟潛力。外資會不會持續有加碼動作呢?我們可以等 thegiive 老師持續為您報明牌 XD

11/07/2006

Orielly 書市報告:Ruby 銷售還在暴漲

2006年 Q3 的 O'Reilly 書市報告出來了 ,Ruby 一如預料的銷售量還在暴漲,成長幅度約為 255% ,雖然沒有上上次 1500%,以及上次的 687%嚇死人的成長率,但是依舊是 Programming Language 成長率第一名。
而書籍總銷售量的部份,Ruby 書籍銷售量在2005 Q4 超過 Python,2006 Q3超過 Perl 。不過離 Javascript 跟 PHP 書籍還有一段路要走。



而 Ruby on Rails 書籍細部的部份
Ruby on Rails, another relatively new category, has also become very competitive. The Pragmatic Programmers' initial groundbreaking book, Agile Web Development with Rails, which once had the market to itself, now competes with at least three other titles, including the Prags' own Rails Recipes and Manning's Ruby for Rails O'Reilly's Ruby on Rails: Up and Running has taken the top spot, but the book is too new to know whether or not its sales level will stick.
Ruby on Rails 終於成為 Web Design 其中一個分類了(之前只有一兩本書不能當作一個分類)。Agile Web Development with Rails 也不再壟斷市場,他受到 Rails Recipes ,Ruby for Rails ,Ruby on Rails : up and Running 這三本書的競爭。

本篇文章圖片皆出自 O'Reilly Radar

11/06/2006

37 Signal + Amazon ?

今天看到一篇很八卦的文章,內容是 Amazon 老闆 Jeff Bezos 投資一些錢給 37 Signal 。(並非 Amazon 投資 37Signal,而是 Jeff Bezos 的個人創投公司

Bezos Expeditions, a personal investment company of Jeff Bezos, has made a minority private equity investment in 37signals.

然後這位八卦的老兄開始猜啦,難道會是 Amazon 跟 Ruby on Rails 一起合作搞一個 Ruby on Rails 的 Web Hosting 嗎?

我覺得這個推斷實在目前言之過早啦。不過當然我們都知道 37 Signal 是推銷 Ruby on Rails 的大本營,他們這個企業也擁有 Ruby on Rails 的創造者 DHH ,可以說 37 Signal 的價值大多數也是建立在 Ruby on Rails 身上。Jeff Bezos 又是 Amazon 的絕對掌權者,他可不是善心人士,是商人,他的動作某種程度可以看到 Amazon 的風向。他要是肯投資 37 Signal 一定代表他想從 Ruby on Rails 這邊得到什麼。我推斷他要的不是名聲,如果他要名聲,大可捐錢給 Ruby on Rails 開放原始碼社群,而不是投資一家營利企業。說是看好 37 Signal 的營利嗎?我也覺得太牽強了一點,雖然他們似乎頗賺錢。

我的感覺是他想獲得 37 Signal 目前領先業界的東西
Ruby on Rails 的技術力
也就是說,Amazon 有興趣在 Ruby on Rails 上面,而且希望能夠跟 Ruby on Rails 指標性技術公司合作。或許是幫助架設網站,也或許是原作者所推斷的 Web Hosting 合作服務,也或許有其他的合作案。(當然也有可能是 37 Signal 被併構,不過可能性不高)總之,Ruby on Rails 已經獲得 Amazon 這樣大公司的注目是不爭的事實,其他的東西就 wait and see 吧。

延伸閱讀:
  1. Mr. Six 好文一篇

ERubis :快三倍的 ERB

這個網頁看到的好東西。一個語言一開始速度不佳沒關係,只要一紅起來,一定會有人幫你加快速度的。JAVA 一開始是這樣沒錯,看起來 Ruby on Rails 漸漸要開始脫離速度尚可的名聲了。Webrick 太慢了,所以 Zed Shaw 寫了 Mongrel 。ERB 速度尚可,就有人寫 Erubis ,讓你的 ERB 可以飛快的執行沒有負擔。

Erubis 是用 Ruby 寫的,但是速度居然比用 C 寫的 eruby 還要快。最重要的是,他可以不用改寫現有的 Rails code ,就直接讓 Rails 使用,這就相當的可怕了。下圖是 ERB 跟 Erubis 的比較圖我們可以發現到他的速度幾乎是 ERb 的三倍快。

安裝

至於安裝方式的部份,我們用 gem 來安裝
gem i erubis

  1. 你可以在 application.rb 或是 config/enviroments/ 裡面加入
    require 'erubis/helper/rails'
    suffix = 'erubis'
    ActionView::Base.register_template_handler(suffix, Erubis::Helper::RailsTemplate)
    #Erubis::Helper::RailsTemplate.engine_class = Erubis::EscapedEruby ## or Erubis::PI::Eruby
    #Erubis::Helper::RailsTemplate.default_properties = { :escape=>true, :escapefunc=>'h' }
  2. 將你的 .rthml 改成 .erubis
  3. 最後要注意,layout 裡面 yield 的部份要改成以前的 @content_for_layout

測試結果

根據我的測試,的確感覺比較快,但是快多少很難說,畢竟 render 所佔的部份不重。相容度的地方,目前一般頁面完全沒有問題, 除了 @content_for_layout 跟修改 template 檔名以外
,完全不用改寫 code 。Cache 跟 AJAX 的部份還不確定有沒有問題,如果沒問題,那這個東西一定會大紅起來。

題外話,這個東西給我的感覺,想做成一個 Univeral 的 template engine ,不只支援 Ruby ,PHP,JAVA ,Javascript,C,Scheme 都有支援,不過支援程度還很小兒科啦@@!

11/05/2006

Rails 的 High Traffic 負載度

看了對岸的 《程序员》10期特别策划:Web开发之华山论剑裡面的評論,裡面有一段(原文為簡體,我直接翻譯成繁體
如果你打算用 Rails 給自己寫個 Blog 或是小型的 Web 2.0 應用很合適,比如 37 Signal 開發的 Basecamp.com 和 Robot Co-op 開發的 43Things.com 採用 Rails,這些Web2.0 的小應用每天頁面訪問幾十萬,數據庫紀錄數不到百萬,負載是比較輕的。
看完真是無言,43Things 最好 Traffic 那麼少,根據 Alexa 的數據,43Things.com 的 Daily Reach 每天大約是 600 Million 。雖然 Alexa 的數據準確性有很多人質疑(我是很質疑這個數字啦),不過這個流量數要硬說成只有幾十萬也差太多了吧。

我列一下一些用 Ruby on Rails 的高 traffic 站台。我之所以用 Alexa 的原因是因為我不可能拿到下面站台的 Traffic 營運資料,所以我只能使用看似不是很準的 Alexa 來比較。

  1. A List Part:Alexa 上面的數字最高衝到 1500 Million Day Reach ,已經是流量很不錯的站台了,Daily Reach 今年一度到達國內 Webs TV 網站的一半
  2. Penny Arcade:Alexa 800 Million Daily Reach,數字是蕃薯藤新聞的兩倍。
  3. 43Things.com:今年上半年 Daily Reach 跟 A List Part 差不多,Alexa 數字是 600 Million Daily Reach,依照比例大概比蕃薯藤新聞多了一點Daily Reach。
  4. Odeo.com:這個站依照 Alexa 大概也跟蕃薯藤新聞差不多,不過少了一點。他是 Podcast 聲音檔案的網站,頻寬的消耗度是相當可怕。(雖然 Ruby on Rails 的覆載度跟 Handle 頻寬的能力,沒有直接關係XD
  5. jobster:一個找工作的 Social Network,平常上去的人不多,只有一二月跟八九月特別多人(找工作的旺季),流量大的時候跟現在的樂多差不多流量。
  6. Basecamp:讓 Ruby on Rails 誕生的指標性網站, Daily Reach 大致上跟 Odeo.com 差不多。我有使用過一段時間,他的權限系統相當的複雜,不用 Ruby on Rails 那麼簡單的東西寫會很難寫。
  7. Eins.de:雖然比他流量大的網站還很多,但是 procs.net 在這篇文章有特別講到他的架構。軟體使用純 Open Source 的架構,硬體使用光華商場叫的到的貨色,一天可以服務 1.2 Million 動態網頁。對 Ruby on Rails 的高覆載度有問題嗎,這篇文章可以打破你的疑惑。
  8. Hemidemi:我所知道國內第一個 Ruby on Rails 網站,站長是我學長 XD,這一兩個月成長開始爆發。
  9. JaveEye:我最常舉的例子,根據通过JavaEye2.0网站看ruby on rails性能這篇的說法,JavaEye 只用到一台光華商場買的到的機器,也就是 Web Server ,DB Server ,Mail Server ,Search Server 都在同一台。純 Open Source 的架構,一天處理個 50 萬應該沒問題。
如果這些網站,還無法堵住『如果你打算用 Rails 給自己寫個 Blog 或是小型的 Web 2.0 應用很合適』這樣的嘴,那麼我也沒話說了。因為 Ruby on Rails 很年輕,所以用 Ruby on Rails 開發的站台大多營運時間只有一年不到,一個新興網站其實有上面那麼多流量其實已經很嚇人了。如果再過個一年,或許會有流量更驚人的 Ruby on Rails 網站出現。

最後,當網站負載度到達一定程度,任何語言都不能可能承擔這樣的流量,所以網站的負載度還是看彼此的架構好壞,不是取決於語言本身,絕對沒有一個站台只靠 PHP 或是 CGI 就可處理所有Request 的。語言或是框架對於乘載度的差別在於『轉換高流量負載架構的彈性』,這點 Ruby on Rails 作的真的不差。

PS. Measure Map 是用 Ruby on Rails 寫的,已經被 Google 買下來。

TIOBE 11月排行:Ruby 大邁進

終於出爐了,出處在此。這個月果然如上個月預料超越了 SQL 成為第 12 名,不過根據上個月的推測,本來以為可能會多花點時間從 1% 上升到 2%。結果這一個月的上升的幅度高達 0.635%注1)。這個上升幅度實在是相當的驚人,TIOBE 的標題也用 Ruby is rocketing skywards來形容這個月 Ruby 的大邁進。照這個上升率,說不定下個月就直接三級跳,幹掉 SAS ,Delphi,Javascript 成為第九名。只要晉升到前十名,名單上大概都是赫赫有名的程式語言,也正式宣告 Ruby 進入主流語言的行列。下面的表是這周的排行,下面的圖是今年 5 月 Ruby 進入前 20 名之後的上升圖。

注1上個月的佔有率是 1.082%,這個月大幅度升高到 1.717 %

Position
Nov 2006
Programming
Language
Ratings
Nov 2006
Delta
Nov 2005
Status
1 Java 20.400% -1.87% A
2 C 17.198% -1.16% A
3 C++ 11.055% +0.25% A
4 (Visual) Basic 9.470% +1.89% A
5 PHP 9.209% -1.57% A
6 Perl 6.228% -0.91% A
7 Python 3.641% +0.87% A
8 C# 3.023% -0.26% A
9 JavaScript 2.310% +0.43% A
10 Delphi 2.252% +0.79% A
11 SAS 2.210% +1.03% A
12 Ruby 1.717% +1.28% A
13 PL/SQL 1.223% +0.15% A


Comet For Ruby on Rails and Mongrel

Comet 這個詞出自於 Dojo 作者 Alex Russell 在 2006/3/3 發表的 Comet: Low Latency Data for the Browser 。簡單來說就是讓 Browser 跟 Server 作一個長時間不斷線的連線,然後我們要在 Web 撰寫 Rich Client 的程式就相當的容易。有人推測這可能是一個超越 AJAX 的技術。

Comet 跟一般常用的 AJAX Polling 作法有相當的不同。Polling 簡單來說就是每過一段時間,去問 Server 有沒有變化,這個作法的好處是不更改現行的 Web Server 架構即可做到,缺點是會造成 Server 跟頻寬相當大的負擔。下面有一份 Alex 畫的 AJAX 與 Comet 之間流程比較圖



至於 Comet 的目的是讓 Client Server 保持連線,Server 狀態一有改變,就傳一份給 Client。作法有 HTTP_StreamingServer Push,HTTP Streaming 我還沒有 survey ,不過 Server Push 技術我發現 vgod 的文章講的很好,也很清楚
這個方法一開始還是由client先對server建立連線,但是server在建立起連線後,送出的header中要把content-type設為” multipart/x-mixed-replace”,意思是server之後要分好幾次送出許多片段資料,請client保持連線不要中斷,並且把每 次拿到的新片段取代之前的舊片段。接著,client就只要在這條保持不斷的HTTP連線上等著收server送過來的資料就好了。
Comet 的好處是不用像 Polling 一樣耗費太多不必要的頻寬,壞處是 Web Server 架構要修改程式成 Comet 的運作方式,在Browser 部份也有問題要修改,因為 IE 不下載完成就不顯示網頁,必須使用 iframe 或是 Flash 來幫忙做到抓取即時資料的任務。在目前來說,因為缺乏 Server 大環境的支援,短期內大流行的機率不高。目前已經有 Lightstreamer 的即時財經訊息,感覺很不錯。(下圖為 lightstreamer 裡面的即時股市資訊
這是目前使用 Comet 技術的公司已經有
介紹完 Comet 了之後,你認為這還只是構想而已嗎?我發現到 Ruby on Rails 社群對於 Comet 是相當接受,現在已經有 Comet 的 Plugin : Juggernaut 。這個 Plugin 附帶了一個用 Ruby 寫的 Push Web Server,在 Browser 端使用 Flash 6 來接收 Server Push 過來的資料,可以說是實做相當的完整。這裡也有一份簡介。另外也有人寫了一份擁有 Comet 功能的 Mongrel 。看到這邊,已經很興奮了。我們可以使用 Juggernaut 的 Flash 6 Client ,然後 Server 端使用 Reverse Proxy 轉到 Mongrel Cluster當作 Web Server ,這樣環境架設問題似乎都解決了。



仔細看看這種作法, Reverse Proxy + Mongrel Cluster 幾乎也是 Ruby on Rails 社群的標準作法,不論速度或是穩定度都表現都相當不錯。而且這種搭配方式可以用最少的伺服器轉換成本(不用改寫 Apache 或 Lighttpd),而達成 Comet 的目標。也就是說,Comet On Rails 已經不是只聞樓梯響的階段了,只要 Comet Mongrel 進入 Stable 階段,隨時可以給企業使用。

參考閱讀
  1. Comet: Low Latency Data for the Browser
  2. Comet : 超越 Ajax 的新技術?
  3. Juggernaut: Comet for Rails?

11/04/2006

YARV 還在進步

雖然上一篇本人基於 YARV 的單打獨鬥,對於他的未來產生質疑。不過今天 JavaEye Suninny又提出一篇關於 11/1 svn 版本的 YARV 的 Benchmark ,11/1的版本不論執行時間或是Memory耗費都有一定程度的進步,讓我馬上把對 YARV 發展速度的質疑都吞了回去。底下是測試數據,Test Case 在這裡有詳述

A 實驗,在Ubuntu 下面測試,YARV SVN : 9/17 vs 11/1
執行時間
9/17 : 3.36 sec
11/1 : 3.10 sec
Memory
9/17 : 91M
11/1 : 64M

B 實驗,在Ubuntu 下面測試,YARV SVN : 9/17 vs 11/1
執行時間
9/17 : 4.11 sec
11/1 : 3.73 sec
Memory
9/17 : 3.2M
11/1 : 2.2M


我個人是比較看好 JRuby 的發展,畢竟商業的力量才是推動世界進步的主力。但是 YARV 才是我內心真心為他搖旗吶喊的 VM ,加油呀。(我 C 超級差,沒辦法幫上忙寫Code >_<

11/03/2006

Ruby Thread

JavaEye 有一篇文章 Ruby的伪线程,講述的是 Ruby 在 Thread 的問題。在目前為止,Ruby 的 Thread 還不是 native thread ,所以根據 jack 的說法
这样做的确使得Ruby的Thread很容易控制,程序也不容易产生类似死锁这类严重的线程问题。但是效率始终无法提高,因为在ruby进程中,实际上只 有一个真实的线程在运行,同样的代码在那么多核或者多cpu的电脑上运行效率和单核cpu的电脑上的效率并不会相差多少。
當然 Thread 對於 Performance 對於效能的進步是有很大的幫助啦。不過目前 Ruby 上面最有希望的 Native Thread Virtual Machine :YARV 目前處於緩步狀態。(一個人作實在太操了)並且 YARV 到目前並沒有完整的計畫支援 continuation 的計畫,這實在對 Ruby 社群更加減少了使用 YARV 的動力。

根據 Another Year, Another Interpreter 這篇文章,更是拋下一個震撼彈
And then Matz and Koichi dropped the bomb: Ruby 2.0 would support neither continuations nor green threads.
真是太慘了,看來 Thread 在 Ruby 還是遙遙無期。這時候,Ruby 社群應該把重心投入在 YARV 上面,還是剛剛傳出大捷報的 JRuby 上面呢?畢竟 JRuby 是 Native Thread 的,目標也是可以在 JVM 上面跑 Ruby on Rails (目前 JRuby 確定可以跑 Active Record )。這似乎是一個好選擇,不過 Ruby 社群是不是願意將所有籌碼壓寶在 JRuby 呢?JRuby 現在可是由SUN 這家商業公司所主導的。

當然就算 Ruby 支援 Thread ,也會有很多問題要解決。Rails 本身不是 Thread Safe 的,Zed Shaw (Mongrel 作者)也說 Meta Programming 有很多 Thread Safe Probelm 。總之,Thread on Ruby 是一個難題,短期內也應該不會有很好的解法。

11/02/2006

簡單的回應 JeffHung 的文章

偶然看到JeffHung 一篇文章
我還是不了解 RoR 好在哪裡。Web application 的問題一直都在套版與 scaling。套版問題將會隨著 CSS 的普及,以及如 ZK 這類 framework 的出現,而得到解決;而 scaling 則要看工程師們所施展出來的種種藝術。但我認為 RoR 根本沒有解決這些重要的事。
Ruby on Rails 的好處在於開發時間的大幅度縮短,以及程式碼的量大幅度減少,關於這兩點我想我 COSUP 講得很清楚了。至於套版的問題?老實說我無法抓到這個點。或者說,我根本不知道目前 Web Application 有啥樣板的問題,所以就不回應了。

Scaling 的問題很重要,但是這不是 Ruby on Rails 或是 PHP 應該作的事情,這是 Web Server ,DB Server ,Application Server 要作的事情。沒有任何一個大網站可以只用一個語言就可以 Handle 所有的 request ,一切都還是要歸功於 CIO/MIS 背後架構規劃,軟硬體設定的功力,這是任何一家公司躲不掉的付出。如果你希望一個框架就可以解決 Scaling 問題,不如先去問小叮噹比較快。

你所選用的框架或是語言能夠為 Scaling 所做出的付出,就是隨時保留 Scale 的彈性,這點 Ruby on Rails 可以使用 Mongrel ,Memcache Client,Capistrano ,View Cache ,Multi DB 等等 Solution ,都賦予Ruby on Rails 相當大的彈性去作到 Scale。如果你想看範例圖的話,proc.net 這一篇文章裡面圖的部份就很清楚,或是使用 Reverse Proxy 的動作來作 Scale 的議題。這次 COSUP 的 Talk ,我將重點鎖定在開發時間,但是並不代表 Ruby on Rails 只有開發時間強。很多東西要講真的可以講的很細很繁瑣,如果真的要花時間講出來,相信大家也覺得很無味,所以我選擇不討論。

RoR 可以大幅簡短開發時間?任何一個資深的 PHP programmer 大都早已自己實做了一套自用的 RoR,以應付那些層出不窮的小型資訊系統專案,差的只是包裝好壞罷了。
究竟有那套 PHP 寫出來的東西,或是那個資深 PHP Programmer 寫出來的 Framework ,開發時間可以媲美 Ruby on Rails ,請拿出來,我很想看看。Framework市面上一堆,但是開發時間像 Ruby on Rails 那麼神奇的,抱歉,我認為目前沒有。(個人用過 Symfony 跟 CakePHP ,對於他的優缺點都略有了解)如果 PHP 真的已經有那麼好的框架,那那麼多人一窩蜂花時間去學名不見經傳的 Ruby 是嫌時間太多嗎?
在理想上,若 rails 做得好的話,可以在內部搞定。但這是理想,rails 還這麼「年輕」,我不認為可以搞定 Complex/optimized SQL statement construction from object-oriented context 這件事。
基本上,如果這個 Framework 是針對 MySQL 或是特定一個 DB,這是有可能做到的。但是 Ruby on Rails 身為一個跨 DB 平台的 Framework ,他本身設計上,就不應該存在著 Complex/optimized SQL statement 的概念,因為每個 DB 對於 SQL optimize 的方式都有相當大的不同。但是 Ruby on Rails 在設計上面就已經有optimized SQL statement 容許的彈性 。如果單純是用在 retrive 上面的話,find_by_sql 加上 Active Record 去處理 Bottleneck SQL 已經相當夠用。如果是其他 SQL ,在 Ruby on Rails 裡面,我們還是可以做到針對特定 DB 進行內部 SQL 實做的 Optimize ,而且因為 Ruby 語法 Open Class 的關係,很容易實做出來。

我絕對不反對有人提出質疑,討論時白刀子進紅刀子出比較容易跑出更好的結論。所以,你可以在這個 Talk 過程中 Challenge 我,我很喜歡這樣,因為通常會激出一些新的火花。或許你也可以私底下問我,寫信給我討論,如果是 Web Design 或是 Ruby on Rails ,我最起碼還回答得出一些東西。但是如果你不問我,也不去試著去了解 Ruby on Rails,就因為rails 還這麼「年輕」這個理由,就給予『我覺得RoR作不到...』這樣的批評。這不是一個很好的方式,也不是一個很好的求知態度。

11/01/2006

為你的 N:M Join Table 加入屬性

原本的設計

N:M Join Table 一般來說,通常只有兩個 Column ,兩個都是另外兩個 table 的 Foreign Key。舉例來說,假設今天有兩個 Table ,一個是 people ,另外一個是 firend_relations。人跟人之間的朋友關係由 friend_relations 來描述,所以 friend_relations 裡面的欄位應該有
  1. person_id
  2. friend_person_id
根據 Agile Web Development with Rails這本書,裡面有一段話
Active Record automatically includes all columns from the join tables when accessing rows using it. If the join table included a column called id, its id would overwrite the id of the rows in the joined table.
如果 join table 裡面,加上 id 這個欄位的話,當我們使用
Person.find(1).friends.each do |friend|
puts friend.id
end
這裡的 i.id 不是朋友在 people 這個 table 裡面的 id ,反而是 Join Table friend_relations 的 id 。也就是說,Join Table 裡面除了 Foreign Key 以外的欄位,都會覆蓋掉所有關聯性 Table 的欄位。這在 Coding 時,很容易造成混淆,必須盡量避免。

好處?

但是有時候這個特性很好用,假設有一需求。我想知道我跟你之間的朋友關係是啥時建立的?我們如果將這個時間 created_at 寫在 Join_Table frined_relations 裡面,那麼
Person.find(1).friends.each do |friend|
puts frined.created_at
end
這裡的 i.created_at 就是 freind_relations 裡面的 created_at (朋友關係建立的時間),而非 people 裡面的 created_at (person 資料建立的時間),因為已經被覆蓋掉了。的確,當你使用到 person.friends 的時候,通常你在使用 朋友關係 的資料,而非 這個人的基本資料 ,所以他被覆蓋過去也是很合理的。

我們還可以在 friend_relations 加入 relation 這個 column ,裡面放 '點頭之交' ,'朋友' ,'好友','密友' 之類的關係,可以作出
Person.find(1).friends.each do |friend|
puts friend.name+'是'+friend.relation
end
結果就會出現
小李是好友
小王是點頭之交
小陳是朋友
之類的結果,可說是相當方便的特性。

Bug? 還是特色?

不過今天發現了一個問題,HABTM 的 Table 在 Ruby on Rails 裡面是 read only ,我們無法寫入 Attribute (因為他沒有相對應的 Model),並且當我們使用 << 傳入 HABTM 關係時,我發現到假設 JOIN Table 有任何 column 跟傳入的 Column 同名,他會直接寫入 JOIN Table 裡面,也就是說假設,friend_relations 跟 people 都有 created_at 這個 column
a = Person.find(1)
b = Person.find(2)
a.friends << b
這個時候,friend_relations 裡面的 created_at 的確有新的值輸入,但可惜不是創造關係的時候的時間,而是 b 的 created_at 時間。如果我在 friend_relations 加入一個 Person 原本就有的
column,像是 name 好了 。我發現到執行上面的程式他會直接將 b 的 name 欄位直接寫進去,這真是太有趣了。

根據 Rails 的 Many-to-Many 討論 這篇的講法

主要來說 has_and_belongs_to_many 比較簡單,但是那個 join table 不適合再加欄位值,比如說該關聯建立的時間之類的,雖然 push_with_attributes 這個方法可以塞資料進去,但是卻是很亂的糟方式,已經不被推薦使用。

而 has_many :through 功夫多一些,結構更完整,用新增一個 join model 的方式來建立關聯資料。自己有一個 model class,因此使用上也比較豐富。就像一般 model 一樣,先 new 一個出來,assign 好那兩個關聯物件,再填好其它資料,最後 save 即可。

還有 Many-to-many Dance-off! 讓我新發現到 has_many :through 這個方式。我正在仔細思考重構的方式。不過在 Project 重構之前,我先使用 push_with_attribute 進行簡單的 Bug Fix
class User < ActiveRecord::Base
def add_friend user
firendss.push_with_attributes( user , :created_at => Time.now )
end
end
如此最起碼可以使用
a = Person.find(1)
b = Person.find(2)
a.add_friend(b)

達成最起碼的 BUG Fix。

結論

這個特性已經 缺點多於優點了 ,不推薦。雖然 push_with_attributes 可以寫入,但是不能修改,所以只能作一次性的寫入,像是 created_at 還能用,其他的就有問題了。

中文 Ruby 使用者星球


11/1
因為手邊的機器不能拿來亂用,所以只好找上只有 PHP 的學校機器來架設台灣 Ruby 使用者星球,目的是所有台灣 Ruby on Rails 使用者的 Blog Feed Aggreator 。今天更新了 Mollio 佈景主題,真是太漂亮了。

11/7
我增加了對岸的Ruby 社群的 Feed ,並且改名叫做中文 Ruby 使用者星球,不過首頁主頁看到的還是台灣的文章。

如果有哪位網友想加入的,可以在這篇留個回應給我,我看到就會馬上加入的。

Windows 上面安裝 Ruby on Rails

其實不太想寫 Windows Tutorial的原因是因為
  1. 我手邊沒有 Windows,無法測試正確性
  2. Windows 安裝很簡單,也不太需要寫 Tutorial
是的,我沒有 Windows ,不是因為反微軟,只是單純覺得 MAC OSX 桌面使用比較好用,Linux FreeBSD 架站比較好用,那我幹麼用比較難用的系統?

我可以寫 Ubuntu ,Gentoo,FreeBSD,Fedora ,MAC OSX,原因是因為我都有機器可以測試,不過我就是沒有 Windows。但是因為太多人問我了,連我同事都問我@@!,我還是寫一篇解救一下我的 Gmail 收件夾吧。以下文章均是來自其他網頁報導,我本人沒有機器可以測試,錯了請見諒。

首先在 Windows 上面安裝 Ruby on Rails 很簡單,有兩種方式
  1. 一次大雜燴全部安裝好
  2. 分批安裝
我們來看看第一個方法,也應該是最快的方式,使用 Instant Rails 來一次全部弄好,Instant Rails 網頁上簡介是
Instant Rails is a one-stop Rails runtime solution containing Ruby, Rails, Apache, and MySQL, all preconfigured and ready to run. No installer, you simply drop it into the directory of your choice and run it. It does not modify your system environment.
所以安裝他一次就可以將所有 Ruby on Rails ,Apache ,MySQL 都裝好,有種 Appserv 的感覺。並且你還可以額外安裝 Typo, SCGI, Mongrel, 和 HighLine ,最近他連 Rad Rails 都有附,真是太簡便了。這裡有一個 Tutorial 有關於 Instant Rails ,可以看看。

其次的安裝方式是先裝 Ruby ,再用 gem 安裝其他東西。要在 Windows 上面安裝 Ruby 就使用Ruby oneclick Installer 來安裝即可,聽他的名字就知道他只需要 one click 即可安裝。等到安裝完 Ruby ,Ruby oneclick Installer 會順便裝好 gem ,再利用
gem i rails -y
安裝 Ruby on Rails 就好啦。不過安裝 apache ,mysql.....東西,就可能要你自己好好的 survey 一下。ONLamp 有一篇 Rolling with Ruby on Rails 是一篇不錯的 Tutorial ,可以試試看,這裡也有一篇在winxp中手工安装Ruby on Rails 笔记可以試試看,這裡也有 Robbin 寫的
在Windows平台使用Apache2.2和Mongrel运行Ruby on Rails

至於大家關心的 IDE 部份,我推薦 RadRails ,這是從 Eclipse 改的 Ruby on Rails IDE,可能是 TextMate 以外最好的 IDE,Instant Rails 已經有附,直接拿來用即可。

至於我用啥 IDE 呢?抱歉,我不用 IDE ,我用 VIM 。


補充 Mirror:我這裡 Mirror 了一份最新的 RadRails ,以及最新的 InstantRails