12/30/2007

Ruby 1.9 Release

Ruby 1.9 Release了,根據Ruby慣例,版本小數點後面的數字偶數是穩定版本,奇數是測試用的版本。所以 Ruby 1.9 算是 Ruby 2.0 之前的開發版本,現行的穩定版本還是 Ruby 1.8,所以請不要把你公司的 Production 機器都改成 Ruby 1.9。

1.9 除了語法上面的演進以外,最大的不同就是在於內建 YARV 這個 VM。對於 Ruby 整體效能有相當大的增快,如果 Ruby 跟 Python 2 Fibonacci Sequence 的測試,大概比 Python 2 快了三倍。However ,跟幾年前的 Release 比速度,還真的沒啥好誇耀的 :p

Download 點在這
ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.0-0.tar.gz

Change in Ruby 1.9
http://eigenclass.org/hiki.rb?Changes+in+Ruby+1.9

12/26/2007

Beast 在 Rails 2.0.2 不能啟動的解決方式

昨天 安裝Beast Trunk ,發現在最後 rake db:schema:load 遇到
rake aborted!
undefined method `whiny_protected_attributes=' for ActiveRecord::Base:Class
這樣的 error。根據網路上的回答,應該是 Rails 2.0.2 搞得鬼,解決方式根據這個網頁講的,在 config/enviroment.rb 裡面將這行 comment 起來即可
#config.active_record.whiny_protected_attributes = false
話說,beast 已經 800 多行了,乾脆改成千行以下的 forum 好了 :p

Ps.
Beast 安裝方式
1. 下載下來 beast trunk code
svn checkout http://svn.techno-weenie.net/projects/beast/trunk beast
2. cp config/database.example.yml config/database.yml 並且修改他
3. 建立 schema
rake db:schema:load
4. 修改 config/environment.rb. 裡面的 PASSWORD_SALT
5. 安裝額外的 Gem 像是 RedCloth 或是 ruby-openid

12/10/2007

Leopard,Terminal,Vim,and .... UTF-8

最近買了新的 MacBook ,Leopard 到目前感覺都還很不錯,尤其是大幅度改進的 Terminal.app 。不過,跟我預料的一樣,Terminal 的 UTF-8 問題依舊沒有設定好。所以花了點時間 survey ,順便把一直困擾我的 vim 中文問題一起解決。

Leopard 內建的 vim 是 version 7.0.234 ,GNU bash 是 3.2.17 ,這幾個版本支援 UTF-8 都沒有任何問題,所以其實只是設定檔的問題。

1. 修改 ~/.profile
加入
export LANG=zh_TW.UTF-8
2. ~/.vimrc
加入
if has("multi_byte")
set enc=utf-8
set fenc=utf-8
set termencoding=utf-8
set fileencodings=utf-8,ucs-bom,big5,latin1
else
echoerr "Sorry, this version of (g)vim was not compiled with multi_byte"
endif
不確定是否有沒有更好的設定方式,不過,我已經滿意了。

11/05/2007

JRuby 1.1 Beta 1 Release;這個世界最快的 Ruby Interpreter?

JRuby 1.1 終於出 Beta 了,1.0 -> 1.1 主要的改進都是在於 Performance 的部份,結果是JRuby 已經在大多數的 Test 勝過現行的 Ruby 1.8.6,Ruby code 可以用 AOT 或是 JIT 來 compile 。並且兩者都比現行的 Ruby 來的快,memory 使用也比較少。

當然宣稱歸宣稱,我們也該看看 real rails application performace 的表現如何。Nick Sieger 寫了一篇 JRuby on Rails:Fast Enough 表示 JRuby on Rails 已經跟 Ru
by on Rails ㄧ樣快速了。並且JRuby 核心開發者 Ola Bini表示 JRuby 已經在大>多數的 Test 勝過 Ruby 1.8.6

公說公有理,婆說婆有理,那麼最起碼最起碼 JRuby 效能逼近 MRI Ruby 是不爭的事實。
So,該是進場的時候嗎 :p

11/02/2007

JRuby 1.0.2 Relase

JRuby 發表了 1.0.2 版本,修正許多 Bug 跟支援了 Rails 1.2.5,Rails 1.2.5 跟 JRuby 1.0.1 有問題的人請升級到 JRuby 1.0.2。

10/30/2007

Mongrel 1.0.4 出了

    在歷經將近十個月的等待, Mongrel 終於推出了 1.0.3 版,當然依照慣例,很快的馬上就被抓到很多 Bug,隔天就出了 Mongrel 1.0.4 版。安裝方式官方建議是
    gem install mongrel --include-dependencies -P HighSecurity
    不過,最重要的是 release note 最後一句
    Mongrel 1.1 is coming real soon now with JRuby support and a few other things.
    所以,Mongrel 1.1 要出來了,並且還要加上 JRuby Support。

      It's all about JavaScript

      進入公司至今已經一個多禮拜,因為 Project 因素,整天都在碰 Javascript。其實還蠻充實的,而且也學到不少東西,或許我該為這個Blog改個名字叫 LightyJS 之類 :p 很多時候當你真的寫過 Javascript,才發現 RJS 的好處。總之,或許我該多寫點 Javascript 的東西。






      10/17/2007

      新訓結束了,國防役開始

      入伍前,PTT 上面的版眾已經告誡大家某營某連很可怕,但是還是被國防部排進去這個連隊。經過一連串的酸甜苦辣,我從某精實連出來了。因為這個連實在是很精實,所以沒時間看書。我的HTTP:The Definitive Guide也沒翻到百頁。接下來的一周,找房子,搬家,適應新公司等等大概可以讓我多忙個兩週。看來 LightyRoR 要重新出發可能也要等個幾天。對了,我國防役去友邁科技(主力產品 Urmap.com)。

      還有,最近對讀 Rails Source,玩 Xen ,玩 Linux From Scratch,玩仙劍奇俠傳4 很有興趣。真不知道有沒有時間讓我這樣玩。會不會到最後,只有電動玩到了,其他的東西全部都沒時間呢 :p

      總之,我回來了。

      9/08/2007

      AK47 與 M16 補充

      大家好,我又放假了。看到有人問我,上篇文章,意味著誰代表RoR。我只能說,沒有特別的誰代表誰。

      在技術水準差不多的狀態下,所謂的設計好壞其實只是取捨。Ak47 取了簡單,但是失去了準度。M16 強調準度,但是輕巧的設計卻換來了些許的不穩定,以及較高的訓練時間。換來的結果也沒有誰輸誰贏,只是剛好第三世界國家適合 AK47 ,美國適合 M16。

      越戰這個 case ,Ak47 遠勝於 M16,但是這是在叢林戰這個 domain。其實美軍打贏那麼多場戰役,很多其他的戰爭 case,M16 說不定在其他 case 壓的死死的。只是越戰名氣大而已。

      一切都只是需求的不同而已。

      軟體開發也是如此。在工程師水準相近的情況下,你的選擇通常都只是因為這個任務的需求,而非這個設計方式比較好。

      我所陳述的,是一段歷史,是一個工程設計哲學的頂尖對決,是一個值得去瞭解的他山之石。而非誰代表誰。

      9/01/2007

      AK47 與 M16

      大家好,我是 thegiive,我正在服國防役新訓,先跟大家打個招呼。最近一直沒時間碰 Ruby on Rails ,不過軍中倒是花了點時間研究步槍。賢者總是說到「觸類旁通」這件事情,我也剛好從步槍這種殺人兵器中,看到了一些東西,很值得軟體開發借鏡。在此先警告一下,我只是在陳述輕兵器設計哲學之間的比較,並非鼓吹輕兵器,戰爭等東西,如果認為槍枝是邪惡不能被提及之人,請勿進入本文。

      我研究的東西,就是號稱 20世紀最偉大的武器 AK47 ,跟屈居第二的 M16 的之間的瑜亮之爭。

      AK47 是由蘇聯槍械設計師米哈伊爾·季莫費耶維奇·卡拉什尼科夫設計的自動步槍。這款武器號稱槍中之王,很多第三世界國家的戰爭都看到他的身影。可以說是哪裡有戰爭,那裡就有 AK47。有這樣一句話:「美國出口的是可口可樂日本出口的是Sony電器,而蘇聯出口的是AK47。」

      這不是沒有原因的。 AK47 當初設計的哲學,就是為了「簡單」。他被設計成為任何民眾,在沒有人教導,沒有任何工具,依舊可以在三個小時之內可以徒手拆解結合,並且裝子彈射擊,由此可以知道他的「簡單」,到底是簡單到什麼程度。

      再來因為俄羅斯環境氣候糟糕,他將內部機構組織設計為較粗糙,這代表不容易因為沙土,泥水進去而導致不能擊發,也就是他當初就是為了設計為可以穩定的擊發子彈,就算再惡劣的環境也是如此。後來因為 AK47 大流行,參加了許多場戰爭,擁有相當多的實戰測試,導致他的擊發穩定性更上一層樓。有人戲稱「AK47 掉到泥水中,沒關係甩一甩,繼續打」。

      但是當初社記者因為為了「簡單」,「穩定」,損失了些許射擊準度。導致 300M 外射擊準度很差。

      M16 系列是屬於美國系統,他當初設計的哲學就是為了擁有穩定的設計準度,以及良好的射擊距離。所以他採取相當巧妙的設計(我們輕兵器教官是這樣講的,我沒有研究很深),但是越精巧的系統代表容錯率越低, 第一版 M16 對於環境的容忍程度較差,很容易因為環境因素導致卡彈。美軍在沙漠風暴之中,就常聽說美軍為了避免沙子進入槍口,用保險套套住槍口,形成一種很詭異的情況。

      綜合比較兩者優劣,很明顯的 M16 在射擊準度上面優於 AK47 許多,但是耐用度上面,第一版的 M16 可以說是遠遠輸了 AK47,一直到 M16A2 才比較好一點,不過還是輸給 Ak47 。

      使用率上面,AK47遠遠的贏過 M16,傳說 AK47 有一億隻之多。造成 AK47 大流行的原因很多,
      1. 一來是因為構造簡單,上手簡單,士兵幾乎不用訓練就可以擊發,所以許多第三世界國家喜歡使用 AK47。
      2. 再來就是因為構造簡單,容易仿造,所以很多國家都自己仿冒 AK47,傳說十支 Ak47 只有一支是正版的 AK47。
      3. 再來就是如果你有看軍火之王這部片子,裡面講到蘇聯瓦解,許多將軍失去以前的榮光,為了錢,他們將軍火庫裡面成千上萬的 AK47 盜賣給軍火商,導致黑市 AK47 大流行,既便宜又好用。
      4. 最後雖然 AK47 不準,但是第三國家沒有資源去花時間訓練士兵射擊準度,所以使用 AK47 根本沒差

      這裡必須要提一件題外話,如果你看過血鑽石這部片子,就知道他們是怎麼訓練娃娃兵的。而娃娃兵雖然知識水準不高,但是因為 AK47 實在是使用上太簡單了,所以導致軍閥隨隨便便訓練娃娃兵,他們都可以上手,拿槍來殺人, AK47 的簡單某種程度導致娃娃兵的大流行。這是讓我每次看到都覺得很荒謬的一件事情。

      真正決定 AK47 王者地位的戰役就是越戰。越南一方使用 AK47,美軍使用 M16。越戰是叢林戰為主,叢林戰的攻擊射程可能根本不到 10 m ,在叢林 AK47 跟 M16 射擊射程都是一樣的,也就是 M16 的強項射擊距離跟經準度就跟廢了一樣。再加上叢林環境太過惡劣了,M16的低容錯率造成大量卡彈的發生,很多美軍屍體旁邊都有卡彈的 M16,代表他們是因為卡彈才死去的。到後來,甚至出現許多美軍將自己 M16 放在一旁,反而使用搶來的 Ak47 來打越南軍的怪現象。

      事後想想,AK47 早就已經實戰好幾年了,那時的穩定度以經是 3.0 版。M16 在越戰時穩定度還是 1.0 Pre release 版。再來剛好遇到 M16 強項被極小化,所以才會遇到被 AK47 八的那麼慘的情況。

      雖然剛剛講了那麼多 M16 的壞現象,但是他依舊美軍最佳的利器。因為美軍戰爭時需要「減少傷亡」,減少傷亡最好的方式就是拉遠戰鬥,所以 Ak47 只能較近距離的特性依舊不適合美軍。也就是說,沒有最好的槍枝,只有最適合這次任務的槍枝。

      所謂的簡單就是美,在 AK47 留下的最好的證明。簡單的設計容易修改,複製。產品正確率也較高。並且容易上手就容易造成流行。軟體又何嘗不是如此。

      穩定性的重要,在輕兵器的領域優先權是相當高的,畢竟子彈往身上跑過來的時候,誰都不希望自己手上的槍枝卡彈。越戰時,AK47就在這個領域上面遠遠勝過 M16,也為這次比試留下了勝利。當某個領域的要求穩定性,已經高到一個很重要的程度時,我們應該選擇比較穩定的設計,而非功能比較強大的設計。

      最後,沒有最好的槍枝,只有最合適這次任務的槍枝。同樣的,沒有最好的軟體,只有最符合這次任務需求的軟體。

      我們在這些輕兵器的歷史中,是不是看到許多軟體開發的影子呢。

      8/22/2007

      Fedora Core 6 上安裝 beast (3)

      覺得 pound + lighttpd 太麻煩嗎?又翻到一個應該不錯的選擇,
      是一個俄國人寫的 http server, 也具有 reverse proxy 和
      load balancing 的能力。

      godfat ~ 3.2$ port info nginx
      nginx 0.5.29, www/nginx (Variants: universal, dav, flv, mail, ssl)
      http://nginx.net/

      Nginx ("engine x") is a high-performance HTTP(S) server and reverse proxy,
      as well as an IMAP/POP3 proxy server. Nginx was written by Igor Sysoev for
      Rambler.ru, Russia's second-most visited website, where it has been running
      in production for over two and a half years. Igor has released the source
      code under a BSD-like license. Although still in beta, Nginx is known for
      its stability, rich feature set, simple configuration, and low resource
      consumption.

      這個字實在是很難記…不過討論翻來翻去,他 serve static file 的效能和
      lighttpd 在伯仲之間,而 load balancing 是正常可用的。所以與其使用
      pound + lighttpd, 單用 nginx 可以簡化一些流程。我想缺點就是設定上
      還是比 pound 複雜些,不過我個人是覺得比 lighttpd 簡單了。另外 nginx
      好像沒有 windows 版,而 pound 和 lighttpd 都有 windows 版,
      我想這對某些情況可能也是個考量吧?

      雖然之前因為英文文件太少所以不太流行,但最近似乎還算有蠻多人推薦的,
      而且這在俄國好像還蠻廣泛被使用的,試試應該無妨。

      sudo yum install nginx

      跟 lighttpd 一樣,一起丟到 beast 目錄下比較容易管理。
      cp /etc/nginx/nginx.conf \
      /home/YOUR_NAME/projects/beast/stable-1.0/config/nginx.conf
      cp /etc/nginx/mime.types \
      /home/YOUR_NAME/projects/beast/stable-1.0/config/mime.types
      前者是 config 檔,後者是 mime-type 設定檔,會被 include 進去。

      nano config/nginx.conf
      =======================
      user YOUR_NAME YOUR_NAME;
      worker_processes 1;
      pid /home/YOUR_NAME/projects/beast/stable-1.0/tmp/pids/nginx.pid;

      error_log /home/YOUR_NAME/projects/beast/stable-1.0/log/nginx_error.log;

      events {
        worker_connections 1024;
      }

      http {
        include /home/YOUR_NAME/projects/beast/stable-1.0/config/mime.types;
        default_type application/octet-stream;

        log_format main '$remote_addr - $remote_user [$time_local] $request '
                        '"$status" $body_bytes_sent "$http_referer" '
                        '"$http_user_agent" "$http_x_forwarded_for"';

        access_log /home/YOUR_NAME/projects/beast/stable-1.0/log/nginx_access.log main;

        sendfile on;
        keepalive_timeout 65;

        gzip on;
        gzip_min_length 1100;
        gzip_buffers 4 8k;
        gzip_types text/plain text/html text/xhtml text/css text/javascript;

        upstream mongrel {
          server 127.0.0.1:2000;
          server 127.0.0.1:2001;
          server 127.0.0.1:2002;
        }

        server {
          listen 80;
          server_name localhost;

          location ~ ^/(images|javascripts|stylesheets)/ {
            root /home/YOUR_NAME/projects/beast/stable-1.0/public
            expires 30d;
          }


          location / {
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_redirect off;
            proxy_pass http://mongrel;
          }
        }
      }
      =======================

      其實還有一大堆設定我省略掉了,可以自己上官網或 google 找其他的設定。
      啟動:
      sudo nginx -c config/nginx.conf
      關閉:
      sudo kill `cat tmp/pids/nginx.pid`

      我用這個去跑 YSlow, 應該是設定的關係,分數從 62 => 75...
      但當然以我測試機的超低流量來看,就算直接用 mongrel 應該也是瞬間反應…

      8/15/2007

      Fedora Core 6 上安裝 beast (2)

      不喜歡 apache 嗎?apache 沒辦法用 mod_proxy_balancer 嗎?沒關係,我找到另外一個不錯的方式了,是 pound + lighttpd. 如果不想用 apache 的話,上一篇的 httpd 相關的東西都不要灌,改灌:

      sudo yum install Pound
      sudo yum install lighttpd

      我是覺得這邊分大小寫很沒意義,不過 yum 就是這樣﹍。

      pound 是什麼?
      The Pound program is a reverse proxy, load balancer and HTTPS front-end for
      Web server(s). Pound was developed to enable distributing the load among
      several Web-servers and to allow for a convenient SSL wrapper for those
      Web servers that do not offer it natively.

      lighttpd 我想大家都知道,一個非常快速的 http server, 只不過他的 mod_proxy 似乎有很多問題,以致於沒辦法用他。所以這部份用 pound 當前端解決這個問題,流程變成:

      http request => pound => lighttpd or mongrel cluster

      安裝好後,先來設定 pound, 不過 https 就先暫時略過不管。
      sudo nano /etc/pound.cfg
      =========================
      User "pound"
      Group "pound"

      ListenHTTP
          Address 0.0.0.0
          Port 80
      End

      Service
          URL "/(images|stylesheets|javascripts)/"
          BackEnd
              Address 127.0.0.1
              Port    1999
          End
          Session
              Type    BASIC
              TTL     300
          End
      End

      Service
          BackEnd
              Address 127.0.0.1
              Port    2000
          End
          BackEnd
              Address 127.0.0.1
              Port    2001
          End
          BackEnd
              Address 127.0.0.1
              Port    2002
          End
          Session
              Type    BASIC
              TTL     300
          End
      End
      =========================
      前面的設定是把 host/images, host/stylesheets, host/javascripts 這三個 url 下的 request 都丟給 port 1999 處理,也就是等會 lighttpd 要使用的 port. 這邊使用 regex, 可以自由設定自己要的規則。假使未來 user 要使用 file_column, 可以再加個 user/avatar 之類的。

      下面的則是全部丟給 mongrel_cluster 處理。設定上應該比 apache 簡單地多。可以先測試看看,先把 lighttpd 的部份 comment 起來,啟動 pound 試試:
      sudo pound

      照理說這樣就能使用了。不行的話加個 config 檔路徑給他:
      sudo pound -f /etc/pound.cfg

      這邊我是在想要不要把 config 也放到 beast 裡面,不過 pound 應該只會有一個,所以我想還是放到 /etc 下好了。停止 pound 的方式:
      sudo kill `sudo cat /var/run/pound.pid`

      製作 lighttpd 設定檔:
      nano config/lighttpd.conf
      ==========================
      server.modules = (
      "mod_access",
      "mod_accesslog"
      )

      server.port = 1999
      server.bind = "127.0.0.1"
      server.document-root = "/home/YOUR_NAME/projects/beast/stable-1.0/public"

      server.username = "YOUR_NAME"
      server.groupname = "YOUR_NAME"
      server.pid-file = "/home/YOUR_NAME/projects/beast/stable-1.0/tmp/pids/lighttpd.pid"
      server.errorlog = "/home/YOUR_NAME/projects/beast/stable-1.0/log/lighttpd_error.log"
      index-file.names = ( "index.html", "default.html" )
      accesslog.filename = "/home/YOUR_NAME/projects/beast/stable-1.0/log/lighttpd_access.log"

      # mimetype mapping
      mimetype.assign = (
      ".rpm" => "application/x-rpm",
      ".pdf" => "application/pdf",
      ".sig" => "application/pgp-signature",
      ".spl" => "application/futuresplash",
      ".class" => "application/octet-stream",
      ".ps" => "application/postscript",
      ".torrent" => "application/x-bittorrent",
      ".dvi" => "application/x-dvi",
      ".gz" => "application/x-gzip",
      ".pac" => "application/x-ns-proxy-autoconfig",
      ".swf" => "application/x-shockwave-flash",
      ".tar.gz" => "application/x-tgz",
      ".tgz" => "application/x-tgz",
      ".tar" => "application/x-tar",
      ".zip" => "application/zip",
      ".mp3" => "audio/mpeg",
      ".m3u" => "audio/x-mpegurl",
      ".wma" => "audio/x-ms-wma",
      ".wax" => "audio/x-ms-wax",
      ".ogg" => "application/ogg",
      ".wav" => "audio/x-wav",
      ".gif" => "image/gif",
      ".jpg" => "image/jpeg",
      ".jpeg" => "image/jpeg",
      ".png" => "image/png",
      ".xbm" => "image/x-xbitmap",
      ".xpm" => "image/x-xpixmap",
      ".xwd" => "image/x-xwindowdump",
      ".css" => "text/css",
      ".html" => "text/html",
      ".htm" => "text/html",
      ".js" => "text/javascript",
      ".asc" => "text/plain",
      ".c" => "text/plain",
      ".cpp" => "text/plain",
      ".log" => "text/plain",
      ".conf" => "text/plain",
      ".text" => "text/plain",
      ".txt" => "text/plain",
      ".dtd" => "text/xml",
      ".xml" => "text/xml",
      ".mpeg" => "video/mpeg",
      ".mpg" => "video/mpeg",
      ".mov" => "video/quicktime",
      ".qt" => "video/quicktime",
      ".avi" => "video/x-msvideo",
      ".asf" => "video/x-ms-asf",
      ".asx" => "video/x-ms-asf",
      ".wmv" => "video/x-ms-wmv",
      ".bz2" => "application/x-bzip",
      ".tbz" => "application/x-bzip-compressed-tar",
      ".tar.bz2" => "application/x-bzip-compressed-tar"
      )
      ==========================
      我很想省略 mime-type 設定,不過不設的話 firefox 好像會有問題。safari 和 opera 是 ok 的,IE 我沒得測就沒測了。反正要設就是了,有沒有問題不影響。只是希望 lighttpd 能內建這些設定﹍。

      啟動 lighttpd
      sudo lighttpd -f config/lighttpd.conf

      這樣就算大功告成了!剛剛有測試 pound 的話記得改回原本設定並重新啟動。比較詳細的介紹與說明可以參考這篇:
      Configuring pound with lighttpd and mongrel.

      *

      summary:

      用到的 server:

      (1)
      apache2.2 =>
      reverse proxy + load balancer + serve static files

      (2)
      pound => reverse proxy + load balancer
      lighttpd => serve static files

      (3)
      mongrel_cluster => setup mongrel cluster
      mongrel => serve beast

      結果就是 ((1) or (2)) + (3)

      操作 apache:
      啟動:sudo apachectl start
      停止:sudo apachectl stop
      重啟:sudo apachectl restart

      操作 pound:
      啟動:sudo pound -f /etc/pound.cfg
       或:sudo /etc/init.d/pound start

      停止:sudo kill `sudo cat /var/run/pound.pid`
       或:sudo /etc/init.d/pound stop

      重啟:sudo /etc/init.d/pound restart

      操作 lighttpd:
      啟動:sudo lighttpd -f config/lighttpd.conf
       或:sudo /etc/init.d/lighttpd start

      停止:sudo kill `cat tmp/pids/lighttpd.pid`
       或:sudo /etc/init.d/lighttpd stop

      重啟:sudo /etc/init.d/lighttpd restart

      操作 mongrel_cluster:
      啟動:sudo mongrel_rails cluster::start
      停止:sudo mongrel_rails cluster::stop
      重啟:sudo mongrel_rails cluster::restart

      操作 postgresql:
      啟動:sudo pg_ctl start
      停止:sudo pg_ctl stop
      重啟:sudo pg_ctl restart

      8/14/2007

      Fedora Core 6 上安裝 beast

      我選擇 apache2.2 + mongrel_cluster + postgresql

      安裝 apache 和其他的東西。
      sudo yum install httpd
      sudo yum install httpd-devel
      sudo yum install openssl
      sudo yum install readline

      安裝 ruby
      sudo yum install ruby
      sudo yum install ruby-devel
      sudo yum install ruby-libs
      sudo yum install rdoc
      sudo yum install irb

      安裝 postgresql
      sudo yum install postgresql
      sudo yum install postgresql-devel
      sudo yum install postgresql-libs
      sudo yum install postgresql-server

      初始化 postgres
      sudo mkdir -p /var/db/postgresql81/defaultdb
      sudo chown postgres:postgres /var/db/postgresql81/defaultdb
      sudo -u postgres initdb -D /var/db/postgresql81/defaultdb
      sudo -u postgres pg_ctl -D /var/db/postgresql81/defaultdb \
      -l /var/db/postgresql81/defaultdb/postgres.log start

      拿來抓 beast... 捨 svn 取 svk 因為我討厭一堆 .svn
      sudo yum install perl-SVK

      sudo yum install rubygems

      至少要用這些 gem
      sudo gem install rails -y
      sudo gem install mongrel_cluster -y
      sudo gem install redcloth -y
      sudo gem install ruby-openid -y
      sudo gem install ruby-postgres -y

      建立目錄。
      mkdir -p ~/projects/beast
      cd ~/projects/beast

      用 svk 抓不會有一堆 .svn 礙眼。
      svk mirror //mirror/beast \
      http://svn.techno-weenie.net/projects/beast/branches/stable-1.0/
      svk sync -s HEAD //mirror/beast
      cd stable-1.0

      產生讓 beast 用的資料庫。
      sudo -u postgres createdb beast_prod

      設定資料庫設定檔。
      cp config/database.example.yml config/database.yml

      nano config/database.yml
      =========================
      production:
        database: beast_prod
        adapter: postgresql
        host: localhost
        username: postgres
        password:
      =========================

      初始化 beast 資料庫。
      rake db:schema:load RAILS_ENV=production

      非常囉唆的 cluster 設定,user 可以開 mongrel,
      不過因為我懶所以用自己的帳號跑。
      sudo mongrel_rails cluster::configure -e production \
      -p 2000 -N 3 -c /home/YOUR_NAME/projects/beast/stable-1.0 \
      -a 127.0.0.1 --user YOUR_NAME --group YOUR_NAME

      啟動 mongrel_cluster 吧。
      sudo mongrel_rails cluster::start

      接著是 apache2.2 的 mod_proxy_balancer 的設定,
      如果 mod_proxy_balancer 沒有啟動記得把他打開。

      建立 balancer 導向 port 2000~2002
      sudo nano /etc/httpd/conf/httpd.conf
      =====================================
      <Proxy balancer://YOUR_BALANCER>
        BalancerMember http://YOUR_ADDRESS:2000
        BalancerMember http://YOUR_ADDRESS:2001
        BalancerMember http://YOUR_ADDRESS:2002
      </Proxy>

      Listen 80
      <VirtualHost *:80>
        ServerAdmin YOUR_EMAIL
        ServerName YOUR_ADDRESS
        ProxyPass / balancer://YOUR_BALANCER/
        ProxyPassReverse / balancer://YOUR_BALANCER/
        ProxyPreserveHost on
        ErrorLog /home/YOUR_NAME/projects/beast/stable-1.0/log/apache_error.log
        CustomLog /home/YOUR_NAME/projects/beast/stable-1.0/log/apache_access.log combined

        ProxyPass /images !
        ProxyPass /stylesheets !
        ProxyPass /javascripts !
        Alias /images /home/YOUR_NAME/projects/beast/stable-1.0/public/images
        Alias /stylesheets /home/YOUR_NAME/projects/beast/stable-1.0/public/stylesheets
        Alias /javascripts /home/YOUR_NAME/projects/beast/stable-1.0/public/javascripts
      </VirtualHost>
      =====================================

      接著啟動 apache 就 ok 了。
      sudo apachectl start

      最後來設定 beast 的 smtp, 如果想用 gmail 寄信的話,
      我之前試過兩個方式,一個是使用 msmtp,
      另一個是有人有寫一小段 ssl smtp 的 patch, 可以參考這裡:
      http://www.stephenchu.com/2006/06/how-to-use-gmail-smtp-server-to-send.html

      nano config/environment.rb
      加入:
      ===========================
      ActionMailer::Base.smtp_settings = {
        :address => "smtp.gmail.com",
        :port => 587,
        :domain => 'YOUR_DOMAIN',
        :user_name => "YOUR_GMAIL_ACCOUNT",
        :password => 'YOUR_GMAIL_PASSWORD',
        :authentication => :plain
      }
      ===========================

      nano app/models/user_mailer.rb
      ===============================
      @from = 'YOUR_GMAIL_ACCOUNT@gmail.com'
      ===============================
      我不是很確定這一步要不要做,我猜不做會被 gamil 擋掉。

      接下來把那段程式碼 copy 到可以被 require 的地方,我是放在 lib 下:
      nano lib/smtp_tls.rb
      接著把他 require 進去:
      nano config/environment.rb
      ===========================
      require 'smtp_tls'
      ===========================

      sudo mongrel_rails cluster::restart
      註冊一下試試寄信吧!如果失敗的話,那篇連結裡有個 workaround:

      nano lib/smtp_tls.rb
      =====================
      rescue EOFError
        ;
      rescue OpenSSL::SSL::SSLError => e
        puts('Unexpected Exception: ' + e.message + ' : ' +
          e.backtrace.join("\n") )
      end
      =====================

      我之前用是沒有這個問題,但在這台 fedora 上卻有這個問題,
      也許是要更新 openssl 的版本?不管如何,加入上面那段暫時可用。

      結論:
      還是 macports 好用,速度快,更新快,只是 build 要很久就是了。

      8/13/2007

      ludy 0.0.4 released

      花了一點時間再測試了一下 curry 的實做,i am glad to announce that ludy 0.0.4 is released. 原本的 Proc#curry 被改名為 Proc#__curry__, 我很想把他
      deprecate 掉,但是後來的 Kernel#curry 也有運用到該實做,是有在考慮把他從 public 改到 private, 但考慮到也許還有用處,還是暫時放在 public 下,以後如果發現真的沒用了,會改到 private 下。

      現在的用法是:

      multiply = lambda{|l,r| l*r}

      double = multiply.curry[2]
      assert_equal 8, double[4]
      assert_equal 6, double[3]

      xd = multiply['XD', 5]
      assert_equal 'XDXDXDXDXD', xd

      assert_equal 29, :+.to_proc.curry[18][11]
      assert_equal (0..4).to_a, lambda{|a,b,c,d,e|[a,b,c,d,e]}.curry[0][1][2][3][4]

      只要呼叫到了 Kernel#curry, 且 caller 本身回應(respond_to?):call 和 :[], 則回傳一個 curry function, 這樣就可以有更強的 consistency, 不需要注意什麼時候使用 () 而什麼時候使用 [], 請一律使用 function call/[], 不用擔心參數是否足夠,足夠時就會回傳真正的答案,否則再度傳回 curry function.

      所以其實我是在想,以下兩者是否相同?
      class Array; include Curry; end
      func1 = [].cfoldr
      func2 = [].method(:foldr).curry
      func1 == func2 # => true? or false?

      我的希望是相同,當然。只是我直接換上這樣的實做似乎有點問題,這個狀況可能在 0.0.5 中解決,使 curry module 和 kernel#curry 也能夠擁有該有的一致性。

      另一個棘手問題是 ruby 的 block, 乍看很好用,實際上也是,但是卻造成了很大的不一致。這一點也真的是很難搞定,之前的 this 就有碰上這樣的大問題,使用 yield 似乎無法產生正確的 call stack.

      *

      最後則是 0.0.4 上的實做問題,由於 :*.to_proc 的這個 proc 無法預測其正確的 arity, 就像 :message_that_you_never_know.to_proc 也不可能能知道他的 arity 是多少一樣,這造成了難以判斷何時該回傳正確的值而非另一個 curry function. 我是想要從 Symbol#to_proc 去竄改,不過這會碰上另外兩個問題:

      1. 會跟其他人的實做衝突
      2. caller 和 arity 是合併在一起的,意味還沒 call 之前都不會知道 arity, 這樣我就沒辦法強迫 Symbol#to_proc 能產生正確的 arity.

      所以我只好用另外一個很愚蠢的方式:trial & error.
      begin # let's try if arguments are ready
        self.__send__ :orig_call, *args, &block
      rescue ArgumentError # oops, let's curry it
        method(:call).to_proc.__send__ :__curry__, *args
      end

      效率問題就別提了,我真的覺得這樣很蠢,可是好像也想不到更好的方式。

      所以 0.0.4 就只暫時強化了 curry 的實做,離完善還有很大的一段距離。雖然心血來潮度極高,但好像還算有進展?

      gem install ludy
      to see detail.

      8/07/2007

      ludy 0.0.3 released

      睽違已久,忽然心血來潮多加了幾個東西。
      in CHANGES:
      ==============================
      ludy 0.0.3, 2007.08.07

      1. ludy_ext:
      added:
      1. Proc#curry
      2. Proc#compose
      3. Proc#chain
      4. Symbol#to_proc
      5. Array#foldl
      6. Array#foldr
      7. Array#filter

      removed:
      1. Fixnum#collect # see tc_ludy_ext.rb#test_fixnum_collect for reason

      info:
      1. ruby2ruby has NilClass#method_missing return nil,
      so i can't just make it return blackhole

      2. module Curry:
      see test/tc_curry.rb for usage

      see unit test for usage
      ==============================
      雖然說請看 unit test 來揣摩用法,不過這樣真的有點無趣,所以還是來稍微介紹一下。這次之所以忽然心血來潮想做,是因為看到James Edward Gray II 的 higher-order ruby 專欄:
      http://blog.grayproductions.net/articles/category/higher-order-ruby
      第六篇的:Currying, 他的 curry 實做:
      class Proc
      def curry(&args_munger)
      lambda { |*args| call(*args_munger[args]) }
      end
      end

      老實講,不是說看不懂,可是我不明白為什麼要寫得那麼複雜,乍看之下實在看不太出來。丟掉他的實做,我試著做了一個:
      class Proc
      def curry *pre
      lambda{ |*post| self[*(pre + post)] }
      end
      end

      就我自己測試起來,效果是一樣的,我認為應該簡潔易懂多了。可是這根本不太像 curried function 吧?內心吶喊著。不過在看我後來寫的 curry module 之前,先來簡單介紹一下 currying.

      在 lambda caculus 中,每個 function 都只能有一個 argument, 這是因為 lambda caculus 是一種極簡的語言,用來研究某些模型的語言。但是如果 function 只能吃一個 argument, 有很多事是會做不到的。於是我們可以靠著 tuple 把許多的 argument 包成一個 argument, 例如在 Haskell 中,tuple 就是 (1,2,3), 用括號括起來的就是 tuple. 所以上面的 (1,2,3) 是一個有三個值的 tuple, 可以把他視為一個值。

      比方說有個 function 叫 power, 像是:power 2, 10 會回傳 1024. uncurried function 就會是 power (2, 10), 他吃一個有兩個元素的 tuple, 吐出一個 1024 的值。可是如果是這樣使用的話,其實是很不方便的。有一個方法可以讓 function 依然只吃一個 argument, 但是又不需要使用 tuple, 可以一個值一個值傳入,那就是 curried function.

      在 functional programming 中,function 的地位極高,不管在做什麼事,幾乎都是在操作 function. 這也就是所謂的 higher-order function, 操作 function 的 function, 或是產生 function 的 function 諸如此類。curried function 的效果就是當所吃入的 argument 不足時,他會再吐出另一個 function 去吃其他 argument,直到 argument 足夠時才會吐出結果。

      power 2 的回傳會是一個 function, 他記住了 2, 當他再吃一個 argument 後,則會再把 2 拿出來跟 argument 做運算。所以 power 的 type 會是:
      power :: Int -> Int -> Int
      結合順序是從右邊開始,所以是吃一個 Int, 吐出 (Int -> Int), 也就是吃一個 Int 吐出一個 Int 的 function. 可以想成這樣:

      power2 = power 2
      result = power2 10
      result # => 1024

      也就是說,可以把他看成是一個會不斷記憶 argument 的 function. 看看 James Edward Gray II 的範例:
      multiply = lambda { |l, r| l * r }
      double = multiply.curry { |args| args + [2] }
      triple = multiply.curry { |args| args << 3 }

      multiply[5, 2] # => 10
      double[5] # => 10
      triple[5] # => 15
      triple["Howdy "] # => "Howdy Howdy Howdy "

      所以他的實做其實很簡單,就是用一個 array 記憶 arguments,
      最後再 prepend 到最後的 arguments 裡。
      class Proc
      def curry(&args_munger)
      lambda { |*args| call(*args_munger[args]) }
      end
      end

      不過我覺得不用寫得那麼複雜,所以改寫為:
      class Proc
      def curry *pre
      lambda{ |*post| self[*(pre + post)] }
      end
      end

      這裡利用了 ruby 的 lambda 有 closure 的特性,把 *pre 紀錄下來,再把他 prepend 到 post 上,最後再呼叫原本的自己(self)。

      可是這樣不完整,因為你必須明確表達你需要做 curry, 而 Haskell 的 curried function 是可以讓你忽略這件事的。

      lambda{|a,b,c,d,e|}.curry(1).curry(2).curry(3).curry(4).carry(5)

      這樣不煩死才怪。我希望能用:

      lambda{|a,b,c,d,e|}[1][2][3][4][5]
      也能使用:
      lambda{|a,b,c,d,e|}[1,2][3][4,5]

      可惜我暫時還沒找到好做法 XD 目前暫時僅提供可以 mixin 的 module, 大概是這樣用:

      class Array; include Curry; end

      接著 array 所有以字母開頭的 method 會多個 curried 版,prefix c. i.e., map => cmap; foldr => cfoldr

      func1 = [1,2,3].cfoldr[:-.to_proc]
      assert_equal 2, func1[0]

      做法其實很簡單,就只是檢查參數夠了沒,不夠就重新 curry 一份,夠了就呼叫原始 method. 我原本一直不希望前綴 c, 而以相同名字命名之,然後原本的名字改為:orig_method. 可惜不管怎麼試都失敗,原因不是很清楚,但這種 side-effect 超大的動作,會失敗其實也不怎麼奇怪吧,我想。雖然我總覺得以正常呼叫法而言,應該是沒什麼差才對,也許我有哪裡寫錯了,只是還沒發現而已。

      *

      至於其他新增的東西,這裡也稍微介紹一下。首先 Array#filter 只是 select 的 alias, Array#foldl 也只是 inject 的 wrapper. Array#foldr 稍微複雜些,不過概念上只是類似反過來的 inject 而已。Symbol#to_proc 大家應該都很熟,連 active_support 裡面也有。只是單純的 message/method 轉換而已。

      比較需要提的應該是 Proc#compose 和 Proc#chain. 前者就是數學上的 compose, facets 裡其實也有,不過手癢還是自己做了一份。他有點類似反向的 inject, 很容易做出來。至於 chain, 這是模仿 C++ 的 loki 中的 functor 中的 chain. 效果很單純,就是把 function 串起來而已。這拿來做 callback 應該還算方便,例如:

      button.on_click = menu.method(:popup).chain button.method(:hide)
      接著當按鈕被按下去後,選單就會彈出,且按鈕自動隱藏。
      至於 arguments 和 returns 呢?arguments 會統一給所有人。
      f1.chain(f2)['XD']
      這樣 f1 和 f2 都會接到 'XD' 這個 argument. return 則會蒐集成一個 array 並 flatten 回去。
      [f1 的結果, f2 的結果, f3 的結果,...]
      如果 f3 的結果是 array, 則會依序儲存:
      [..., f3 的結果1, f3 的結果2, f4 的結果, ...]

      這樣做的原因是要讓 chain 還能繼續 chain 而不會出現非常恐怖的 nested array.
      f1.chain(f2).chain(f3).chain(f4)
      但是其實可以這樣 chain:
      f1.chain(f2, f3, f4)
      結果和上面的會是相同的。

      在 chain 之間的 travel 還沒做,下次有機會時會做。

      gem install ludy # to see detail

      ruby 寫起來真的很簡潔,很多功能 10 行內都能解決。

      2007.08.07

      7/28/2007

      Active Scaffold Upload Branch

      我真的被 rails plugin 嚇到了。這幾天試著做 web development, 大家應該都知道我跟這個領域不太熟吧?可是,忽然間我覺得,這樣幾乎什麼都能做了。三個 plugin, 依照我嘗試的時間順序:

      1. FileColumn
      2. LoginGenerator
      3. Active Scaffold Upload Branch

      由於一開始使用 FileColumn 碰到了點問題,所以我有稍微 trace 他的 code, 基本上這個 plugin 我覺得算是小玩具,很簡單的小功能,居然沒內建到 rails 中我覺得有點奇怪。畢竟 binary file 一般都是存到 file system 而非 db 中吧?搭配 rmagick 的感覺還算不錯,可惜 helper 似乎不太健全,雖然堪用了。

      接下來碰到需要 auth 的部份,懶得自己寫,因為只是小地方需要,並不真正屬於我目前所要寫的東西的一部份。重新發明輪子我覺得不是問題,但如果只是想到旁邊的便利商店買罐飲料卻因此得重新發明輪子,呃,這是成本考量與優先序的問題啊。

      於是試了一下 LoginGenerator, 發現﹍。嗯,還真的是很方便。雖然他是個 gem, 但是 generate 出來之後就沒有 dependency 了,而且要自己改什麼也都很容易。於是 auth 的部份也解決了,畢竟我只是要最簡單的 auth.(雖然他安全性做得如何我就不清楚了,沒有仔細看他的程式碼)

      到這裡,我都還不覺得怎麼樣。第三個 ActiveScaffold 就真的嚇到我了。因為那真的是非常完整的實做。rails 內建的 scaffold 實在陽春過頭,(儘管陽春過頭了,第一次看到還是著實相當驚豔,現在有種鄉巴佬進城的感覺)除非是最簡單的資料,不然碰上 association 或是 file column, 全部都沒辦法應付。當然,我是可以自己去改自己去擴充,但同樣是成本與優先序的問題,一定得需要用別人的東西。

      先是找到了 scaffold extensions, 其實我是比較欣賞這種模式。不要產生一堆程式碼,要改什麼,利用 ruby 的 dynamic 機制就好了。只是他文件實在不多,看來看去要擴充好像還滿有難度的,而且雖然號稱支援 association, 卻是﹍。我只能說真的很難用,不過是多個 link 出來罷了,是比沒有好啦,但是應該會邊用邊想打人吧?

      接下來我乾脆直接 google file column + scaffold 算了。就找到了 Active Scaffold Upload Branch, which is evolved from ajax scaffold. 他的 file column 範例,呃,問題一大堆,有些根本就寫錯了,害我試半天試不出來,有點火大。想說調查一下他的 form 到底是怎麼回事,卻發現他居然整個是用 ajax 寫的,所以 rails 有錯誤不見得會回傳,而且 form 也因為動態產生而無法顯示!

      幸好有 firefox 的 web developer 這個 add-on, 裝了很久卻很少在用,帶有僥倖的心情找了一下,發現他的 display 功能非常強大,舉凡頁面上出得來的,全部都能顯示。然後才發現,active scaffold 額外產生了一個 record 去存,這樣的話下面這一行就明顯不正確了!
      <%= file_column_field 'entry', 'file' %>
      我還是頭一次看到範例有這麼嚴重錯誤的,太相信他結果找錯誤找半天。:( 害我又一直懷疑到 file column 和 rmagick 上,看半天覺得應該沒錯才對。而且這一個 method 也不知道是幹嘛的:
       def file_form_column(record, input_name)
        file_column_field 'record', :file
       end
      不是明明就有 partial 了嗎?還是這可以取代 partial? 存疑,不管了。

      總而言之,現在不只是 file column 的 image upload 沒問題,要自訂欄位也沒問題,版面上又相當漂亮,不會因為拉扯而變形,排序、搜尋等等,也都相當不錯。最重要的是,他的 association 模式跟我所需要的幾乎完全一致!可以同步修改,可以隱藏,可以追加,所有基本功能似乎都有了。

      本來昏昏欲睡的我,看到這邊實在是很興奮,這東西就算要直接拿來用,都夠格了。而且我相信有什麼不足的話,要修改也容易得很。這有一大半要感謝 Ruby :)

      老實講,我真想知道硬幹派的 php programmer 看到這些會有什麼想法。一個 phpBB 我看隨便寫一寫說不定就跑出來了﹍。搞不好再過不久,寫網站就真的是只要呼叫 => 修改 => 呼叫 => 修改就結束了。這還真的是很恐怖的一件事。不過同時這也代表著,我們應該把眼光放遠點了。來做個 YouOS 吧!! XD

      ==

      最後我還想講一件事,就是寫程式寫這麼久,從來沒碰過幾次時程預估是太長的。但寫 rails 這兩次,很明顯我都估太長了。而且縮短的程度也是非常的多!我想除了要感謝 library 的強大外,雖然我還沒引進 unit test, 只用了人工 test, debug 難度就已經沒有很高了,大部份的錯誤都不會很難抓。當然,這有一個很大的原因是我現在在寫的東西難度很低,可是在這麼不熟悉的情況下,我覺得能夠這樣就真的是非常厲害的了。

      另一方面其實我是覺得寫 Flash 有趣得多,難度也高得多。但 Flash debug 真的是會讓人想抓狂的一件事﹍。不知道有沒有什麼好用的 debug tool? 不然寫 Flash 永遠進度落後實在是很煩。

      ==

      script/plugin install http://opensvn.csie.org/rails_file_column/plugins/file_column/trunk

      gem install login_generator
      script/generate login

      svn export http://activescaffold.googlecode.com/svn/branches/upload vendor/plugins/active_scaffold_upload

      有時候真不知道用 rubygems 好還是 rails plugin 好,但我想比較不穩定的東西,用後者應該是會好很多吧?self contained 這種事,有時候還滿重要的。

      鄉巴佬全文完。

      2007.07.28

      7/25/2007

      [心得] RubyCocoa

      轉自 ptt MacDev 板

      作者 godfat (godfat 真常) 看板 MacDev
      標題 [心得] RubyCocoa
      時間 Tue Jul 24 21:40:20 2007
      ──────────────────

      嫌 objective-c 太難用嗎?還在等 obj-c 2.0 嗎?先試試 RubyCocoa 吧 XD
      http://rubycocoa.sourceforge.net/

      [quote]
      It lets you write full-stack Cocoa applications in Ruby. It is also possible to write a Cocoa application that mixes Ruby and Objective-C code.
      [/quote]

      how to install?
      有灌 macports 的話:(當然,xcode 是一定要灌的)
      sudo port install ruby
      sudo port install rb-rubygems(非必要,但建議)
      sudo port install rb-cocoa

      文件放在:
      /Developer/Documentation/RubyCocoa

      範例放在:(相當豐富)
      /Developer/Examples/RubyCocoa

      我這裡有一個簡化的 hello world, 可以小瞥一下:

      require 'osx/cocoa'
      include OSX

      app = NSApplication.sharedApplication

      hello = NSWindow.alloc.initWithContentRect_styleMask_backing_defer [200.0, 300.0, 100.0, 100.0], 15, 2, 0
      hello.setTitle 'Hello'

      btn = NSButton.alloc.initWithFrame [10.0, 10.0, 80.0, 80.0]
      hello.contentView.addSubview btn
      btn.setTitle 'Hello World!'
      btn.setAction 'stop:'
      btn.setBezelStyle 4

      hello.display
      hello.orderFrontRegardless

      app.run

      另外可以順便請教一下,如何讓視窗在按下 X 時關閉而不是隱藏嗎?我沒寫過 obj-c(XD), 昨天文件翻來翻去找不到要怎麼做



      另一方面,如果只是要做 GUI 而不需要 call mac 的 api 的話,個人強力推薦 QtRuby

      sudo port install qt4-mac(這個會 build 很久)
      sudo port install cmake

      QtRuby 沒有這麼方便的安裝法,要到
      http://rubyforge.org/projects/korundum/
      抓 qt4-qtruby, 然後進到目錄下:

      cmake .
      make
      sudo make install

      於是就可以正常使用 QtRuby 了,hello world 如下:

      require 'qt'
      include Qt
      app = Application.new ARGV
      hello = PushButton.new "Hello World!"
      hello.resize 100, 30
      hello.show
      app.exec



      Qt 是什麼?
      http://trolltech.com/products/qt
      是我用過最棒的 GUI toolkit, 使用 C++ 語言。可用 GPL 授權或用商業授權(很貴),二擇一(這是 Qt 唯一被批評的點)

      Ruby 是什麼?
      http://ruby-lang.org/
      是我用過最方便的 programming language, 使用 Ruby license(很自由)歡迎來 ptt Ruby 板參觀 :p



      Mac OS 10.5 將搭載 Ruby 1.8.6 + Rails 1.2.3, 想試試 Rails 寫網站嗎?
      sudo gem install rails
      不需要等 10.5 就可以輕鬆試驗了 XD
      http://rubyonrails.org/

      ==

      發完神經了,有傷眼請見諒 XD

      --
      #!/usr/bin/ruby          [露比] /Programming (Kn|N)ight/            看板《Ruby》
      # if a dog nailed extra legs that http://www.ptt.cc/bbs/Ruby/index.html
      # walks like an octopus, and Welcome ~Ruby@ptt~
      # talks like an octopus, then ◢█◣ http://www.ruby-lang.org/
      # we are happy to treat it as █ http://www.ruby-doc.org/
      # if it were an octopus. ◥ ◤ http://www.rubyforge.org/
      --
      ※ 發信站: 批踢踢實業坊(ptt.cc)
      ◆ From: 220.135.28.18

      7/22/2007

      Ruby GUI

      [begin edited2]
      夠了,不要再修改了,後續請看 telnet://ptt.cc 的 Ruby 板或是:
      http://godfat.tw/viewtopic.php?p=1779#1779
      (我電腦關機或沒使用網路時連不上)
      [end edited2]

      [begin edited]

      作者 godfat (godfat 真常) 看板 Ruby
      標題 Re: [心得] GUI
      時間 Sun Jul 22 18:13:32 2007
      ───────────────────────────────────────

      說是這樣說,不過真正開始測試的時候,我發覺﹍

      1. wxRuby
      實在有點難用﹍有一堆不該有的參數要傳來傳去﹍放棄

      2. FXRuby
      mac 上其實是可以用啦﹍只是需要 X11, 不能用 Aqua
      結果就是﹍對 user 來說很難用,放棄

      3. QtRuby
      結果還是得回到 QtRuby...
      cmake .
      make
      sudo make install

      測試了一下,正常可用 Qt4
      不過市面上的文件好像以 Qt3 為多就是了

      嘖,沒有 port install qtruby 真的很可惜
      這樣以後要升級或是反安裝就比較麻煩了
      不知道當初安裝的 source 是不是要留下來以便反安裝作業

      --
      --
      ※ 發信站: 批踢踢實業坊(ptt.cc)

      [end edited]

      關於 computer science 這個領域,除了程式語言(programming language)與物件導向(object-oriented)外,再下一個興趣大概就是使用者圖形介面了吧(GUI). 所以我一直想找個自己喜歡的 toolkit 來用,在 C++ 中無非就是 Qt4 了,不過在 Ruby 中,似乎沒有一個比較完美的 solution, 一個個來看。

      在這之前,我先說明一下我用過的 C/C++/Java GUI toolkit.

      1. MFC, 學校在教如何剪貼 MFC code, 我是叛逆份子,所以一個字都沒聽進去。不用別人說很糟,光看第一眼就覺得很糟,更何況他又是被罵得半死的東西。

      2. wxWidgets, 這算是我第一個使用的 GUI toolkit, 基本上,我認為這真的是個很強大的東西,沒話說。不過最令人嘖嘖稱奇的應該是他跨平台的能力,如果我沒記錯的話,他跨的平台好像比 Java 還多!不過因為風格問題,我不是很喜歡。基本上,我認為 wxWidgets 的風格有些過於老舊,寫起來感覺不是很好。Ruby binding 叫 wxRuby.

      3. Qt, 我想正是因為 wxWidgets 跟我不太合,所以才繼續找下去。不料找到 Qt4, 我認為這應該是接近完美的 solution 了。有人說,Qt 至少領先其他人十年,也許這麼講並不為過。最令人詬病的,大概就是你只能從 GPL 或超昂貴的商業 solution 兩種 license 中選一種。其實我不覺得這對我來說會是很大的困擾,open source 沒什麼不好,雖然 GPL 是有點太激進了些。Ruby binding 叫 QtRuby.

      4. GTK+, 這個其實我不只沒用過,甚至連看都沒看過。理由很簡單,就是我不想用 C 想用 C++. 當然我知道 GTK+ 評價不錯,也有 Glade 和 win32 的 port, 只是似乎沒有足夠的推力讓我去嘗嘗看。

      5. Swing, 會碰這個完全只是因為需要用 Java. 我個人是覺得他跟 wxWidgets 各有千秋,但同樣遠遜於 Qt. 不過也許這樣比較並不太公平,Java 天生就是沒 C++ 強。所以 Qt 遠勝可能是理所當然的?Ruby 要用可以使用 JRuby.

      6. Ultimate++, 其實這個我沒用過,不過看起來是不錯。沒去試主要有三個原因,一,他綁 IDE, 這個我很不爽。二,他的命名法我不能接受。三,Qt 很好。XD 其實你去看他的網站,他有一個範例程式,並用各種 toolkit 來實做。我個人認為這個動作滿不誠懇的,他有故意挑其他人弱點的嫌疑。而且各 toolkit 做到的東西明顯有差異,這樣比並不公平。不誠懇,不喜歡。

      7. Notus/VCF, 這兩樣 toolkit 都有一個很大的特色,就是 template template and template... 基本上用 C++ 當然是要用 template 啊!!不過知道這兩樣東西時我已經有一段時間沒碰 GUI 了,所以並沒有仔細調查這兩個 toolkit 感覺如何。但我想如果沒辦法接受 Qt 的話,這兩套 toolkit 值得一看。

      8. .NET/mono, 這個其實我只用過 Visual C++ 2005 Express 稍微拉了一下介面,感覺還不錯,但直接寫起程式不知道是什麼感覺。Ruby 要用的話,或許可以試試 IronRuby, 不過我個人對 .NET 沒什麼好感,就不去試了。

      9. VCL, Borland 的招牌,我用過 Turbo C++ Explorer, 感覺是﹍基本上我覺得沒有 .NET 好的感覺。而且要跨平台恐怕有點難,所以就不考慮了。更何況這些好像也不算 open source 的吧?

      10. FOX, 這個是我最沒聽過的 toolkit, 是去找 Ruby GUI 時才發現他的存在,所以我一點都不知道他的狀況究竟如何。評價似乎是不錯,而且好像很年輕。只是呢﹍FXRuby 似乎沒有 mac 的 port, 而我也已經有點懶得用 C++ 寫 GUI 了,所以還是暫時跳過吧﹍。基本上沒有跨 win32/x11/aqua 三大系統的 toolkit, 我就沒什麼興趣試了。

      本來只想隨意講一點的,不知不覺就扯多了。接下來看 Ruby 能使用的東西:

      1. tk, 沒記錯的話,這個被 ruby 內建起來了。不過似乎是用過的都說爛,所以還是不要多考慮吧?

      2. FXRuby, FOX 的 ruby binding, 評價相當不錯,唯一的缺點也許是還沒有 mac 版的樣子?我想未來應該值得繼續關切,雖然我還沒看過他程式寫起來像什麼樣子。要試用的話,除了需要安裝 FOX, FXRuby 就:gem install fxruby

      3. wxRuby, wxWidgets 的 ruby binding, 我是看到有人批評寫起來像在寫 C++, 這應該算是一個滿大的缺點,不過看在他功能強大,跨平台能力驚人的份上,還是值得試試看吧。要試用的話,除了需要安裝 wxWidgets, wxRuby 就:gem install wxruby

      4. QtRuby, Qt3 與 Qt4 的 ruby binding, 基本上評價仍然是相當地好,唯一的兩大缺點,第一個是沒有 gem, 不能 gem install qtruby, 第二個是在 windows 上要安裝似乎非常困難,沒有簡單的方法。但我相信假以時日,這兩個問題都能夠解決(嗚嗚)。

      5. Swing, 要灌 JRuby, 我的 macports 似乎找不到 jruby, 我又不想從 sun 的網站抓下來灌,再說,我也沒喜歡過 swing 過,所以就懶得試了。

      6. Mono, 我有灌 mono, 不過不是很清楚能不能用 IronRuby 之類的東西存取,之所以寫在這,算是做個筆記,說不定可以使用這樣。

      7. GTK+, 我不是很確定有沒有 ruby binding, 但我想應該會有才是。不試的理由同上,所以也只是暫時筆記。

      Ruby 的 GUI 比較有名的大概就這幾個了吧。其實我是一直想試 QtRuby 的,雖然 windows 上似乎不太容易使用,但相信假以時日一定可以的。而讓我卻步最大的問題點在於,不能用 gem 安裝,macports 也找不到 QtRuby. 也就是說,我得親自 ./configure make make install, 但我不喜歡這樣,管理不便。所以我決定還是暫時放下他,等他有 gem 或是 port 時再說吧!

      FXRuby 因為沒用過 FOX, 所以也還是放著再說。更何況據說是沒有 mac 版,那我試屁啊﹍。所以左右思量之下,我還是決定先試 wxRuby! 安裝方便,強大的跨平台能力,雖然是 C++ style 而非 the ruby way, 但對我來說 C++ style 也不是那麼地令人排斥,也許有點詭異,但我覺得也可以用自己想要的方式重新 wrap 一次,對 ruby 來說那是如此簡單的事!

      so have a try with wxRuby!

      this is the hello world:

      require 'rubygems'
      require 'wx'

      class HelloWorld < Wx::App
      include Wx
      def on_init
      helloframe = Frame.new nil, -1, "Hello World"
      StaticText.new helloframe, -1, "Hello World"
      helloframe.show
      end
      end

      HelloWorld.new.main_loop


      sudo port install wxwidgets
      sudo gem install wxruby

      閉關百日

      即日起,本人即將到關西營區閉關百日,休養生息以及盡男生該盡的義務,大概今年十一月回來。新兵訓練出來後,就是國防役的生活啦。

      對了,因為新訓好像可以看點書,所以預計會帶本練功秘笈進去練功
      HTTP:The Definitive Guide
      前陣子太忙了,都沒時間看書練鍊基本功好像也不錯。

      7/11/2007

      Passion

      昨天我的一個好朋友告訴我「我好像失去了程式設計的熱情了。」我聽著這句話,突然覺得我蠻幸福。

      要說我從來沒有這種感嘆是騙人的。上上次擁有這種想法的時候,我那時正被論文跟 PHP 搞的很疲憊,剛好遇到 Ruby on Rails ,那種超乎想像的設計讓我完全掉入這個世界,也重新找回程式真正的熱情。

      上次出現這樣的想法的時候,剛好是前陣子案子太忙,事情多到我想殺人。一連串的忙碌讓我忘記了寫程式帶給我的快樂,只是一直感覺到累累累。Ruby on Rails 的東西也是這樣,成長的很快,但是我是不是跟著他一起成長呢?還是一直原地踏步呢?我到底追求的是什麼呢?我得到了什麼呢?

      很幸運,這種疲憊感很快的就不見了,因為我接了這個 Case ,29屆瓊斯盃網站
      小時候,我看著東方,阿龍,阿三等人在瓊斯盃奮鬥,現在呢?我以官網製作者的身份,坐在場邊看著中華隊在場上奮鬥。不一樣的我,一樣為中華隊加油的心情。我為了這個案子,連續熬夜好幾個晚上,連 Blog 都沒時間寫了,就是為了呈現一個最好的瓊斯盃網站。這麼堅持的理由不是因為專業,只是因為我是一個運動迷,我是一個中華隊的球迷,我要為他們加油。

      累是超級累,但是我找回了失去的「Passion」。一個專門屬於我的 Passion。不瞞各位,我 7/23 就要進去軍中新訓三個月,在進去軍中之前可以做出一個這們有意義的東西,真的很開心。

      一年前我開了這個 Blog ,也是這樣的熱情不是嗎?

      我以身為 Ruby on Rails 使用者自豪,我以身為第29屆瓊斯盃官網製作者自豪。不管你是誰,用什麼語言,什麼 Framework,別忘記你的熱情,千萬要對你的工作感到自豪。

      7/08/2007

      ruby facets

      老實講,ruby 有一個地方真討厭,那就是每次都把我想做的東西做完了。有了 ruby, 我不覺得還有需要再自己弄一個程式語言,做得比我想像中的還好。唯一的缺點大概只有 lib 還不夠多,但有了 facets 的話,那也真的是差不多了。
      http://facets.rubyforge.org/
      該有的幾乎都有了,差的只剩下一些小東西。如果早點發現這東西,大概就不會想弄 ludy 了吧。

      不過想用 facets 有點麻煩,例如我想用 Array#shuffle, 就必須
      require 'rubygems'
      require 'facets'
      require 'array/shuffle'
      這麻煩到爆炸了吧!!不過有個好東西:

      require 'rubygems'
      require 'facets/automatic'

      接下來,就放心使用 Array#shuffle 吧!因為 automatic 會自動幫你 require... 我沒去看他的實做,但我猜是建 table 吧。有一個小缺點,例如你想這樣做:

      [1,2,3].shuffle.map &:to_s

      很不幸,這樣會失敗。shuffle 可以正常自動 require, 但是 Symbol#to_proc 不能藉由這個方法自動 require. 如果你寫:

      [1,2,3].shuffle.map &:to_s.to_proc

      這樣是 ok 的,automatic 可以自動 require 該 require 的東西。問題大概出在,&:to_s 是 implicit call, automatic 偵測不到。所以第一次使用,還是必須明確說明需要用到 Symbol#to_proc, 接下來就可以快樂地使用

      [1,2,3].shuffle.map &:to_s

      了。或是前面自己手動 require:

      require 'rubygems'
      require 'facets'
      require 'facets/automatic'

      第二行的 require 可以讓你使用 Symbol#to_proc, 所以就可以直接寫:

      [1,2,3].shuffle.map &:to_s

      快去安裝 facets 吧!!
      gem install facets
      另一個 ruby web framework nitro 0.41.0 也有用到 facets !! 雖然是用 1.4.5 版的,而現在最新的 facets 是 1.8.54(以 2007.07.08 為準的最新版本)有機會也可以試試 nitro
      gem install nitro
      官方網站是:
      http://www.nitroproject.org/
      缺點非常明確!幾乎沒有文件 XD 我很少看到一個東西的文件可以少到這樣。

      不多說了,我現在頭痛就算了,眼睛也很痛。

      6/25/2007

      淺談 Comet PUSH Server 架構

      最近有機會碰到 Comet 或是 PUSH Server 這類的技術,剛好一直覺得之前寫的 Comet For Ruby on Rails and Mongrel不夠有感覺,所以再寫一次。這裡先得講一聲,我的認知就是 Comet == Server PUSH ,有錯請告知。

      HTTP 統治網路界

      簡單來說,一般的 Socket Programming 都是保持一個雙向的連線,可以送可以收。但是 HTTP Design 為了以下理由,設計方向為單向的。
      1. 提高 Server 處理效能
      2. 方便作 cache,Proxy 容易融入
      3. 方便作 Server Farm
      4. 網路發展初期,實體硬體狀況不佳,很容易造成 connection lose,單向傳輸可以有效避免瞬斷
      我跟你 request ,你回我 HTML ,交易完成,connection close,This is HTTP。

      如果以 HTTP 當初設計的初衷「文件交換」來看,我們發現到他設計的非常的好,也相當成功的在當初糟糕的網路環境下成功的生存下來。但是就是因為 HTTP 設計太成功了,導致現在網路業者一股腦兒將各式各樣的 App 放在 HTTP 的架構上,想要用當初只是為了文件交換的協定,變成一個包山包海的協定,自然產生很多問題。

      HTTP 最大的問題在於即時性

      要解決 HTTP 的即時性的問題,有 Polling 跟 Server PUSH 這兩種方式。

      Polling

      我們想要做到即時傳訊,Server 端觸發 Client 事件等等功能,以現行的 HTTP 架構下,都得利用 Polling 的方式來做到。Polling 其實也就是現在的 RSS Reader 的作法,RSS Reader 會每過半個小時,或是一個小時去問對方 Server 有沒有新文章。用 Polling來作即時性的功能,最大的好處在於容易寫,因為他完全符合 HTTP 的架構,但是最大的壞處在於不夠即時。以 RSS Reader 來說,每過一個小時去問有沒有新文章,代表的意思就是有一整個小時的空窗期,你得每過一個小時才知道有沒有新文章。

      以 RSS Reader 的屬性來說,採用 Polling 有很多好處
      1. 我其實不需要知道立刻知道有多少新文章,使用者對於 RSS 的即時性需求沒那麼高
      2. Blog 系統多變,與其設定一個各 Blog 系統共通的 Socket 協定,不如設定一個共通的文件交換格式來的簡單
      但是如果使用聊天室,即時訊息傳遞,Polling 就不是一個好主意了。聊天最怕不夠即時,所以必須加快 Polling Interval,但是會帶來「提高 Server 負載」的後果。你一分鐘 Polling 一次,跟一小時一次,前者的負載是後者的 60 倍。等於你用負載換來即時性。這個在人一多的情況下會造成相當大的負擔。

      因為 Polling 在某些地方不是那麼的好,所以才有 Server PUSH 機制出現。

      Server PUSH

      Server PUSH 是建構在建立一個不中斷的 Socket Connection 下面。一個作法是使用 iframe ,送出的header中要把content-type設為” multipart/x-mixed-replace”,來保持一個不間斷的 HTTP Connection。另外一個作法就是用 Flash 來跟 Server 建立一個 xmlsocket。保持一個不中斷的 Connection ,代表 Server 有新訊息就可以直接傳給 Client,不用等待 Client 過來 request。

      這樣可以帶來的好處就是,Server 有狀態更新才會有網路傳輸,如果沒有狀態更新,就不會浪費資源。而 Polling 是不管有沒有狀態更新,都得花上固定的網路傳輸成本,當然就會比較浪費資源。

      舉個例子,考試成績快出來了,你每個小時都從宿舍去公佈欄看成績出來了沒,假設成績沒那麼快出來,你自然會花上許多無意義的時間在宿舍到公佈欄之間的往返上面( Polling )。但是如果老師有你的手機(不斷線的 Connection ),成績公佈老師就打電話給你,告訴你的成績(Server Push)。這樣不是好多了嗎?

      但是你會問,假設老師打電話給你,你在收不到訊號的地方怎麼辦?假設班上人數太多,老師不是就會打電話打到手軟?

      這剛好講到 Server PUSH 的壞處,第一個壞處是假設 Client 網路不好,connection 造成瞬斷,那麼你的訊息就會消失不見了。另外一個壞處就是,持續性的 connection 很難做到 Load Sharing機制,通常大家都只會跟同一台 PUSH Server 作連接,這台 PUSH Server 在人一多就會產生大負載度的問題。這當然有辦法解決,只是這就已經要討論到很深的地方了。

      雖然 Server PUSH 不是萬能的。不過整體來說,以傳遞「即時性需求高的訊息來說」,PUSH Server 帶來的好處絕對會比 Polling 來的好,這倒是無庸置疑的。

      6/23/2007

      Active Resource 已經打包成 GEM 了

      Rails 1.2 的最新力作 Active Resource 已經是 beta 的 gem 了,以後安裝的人就不用每次都用 svn 下載了。

      安裝方式就是

      gem install activeresource —source http://gems.rubyonrails.org

      6/22/2007

      SliceHost 入手

      我是程式設計師,工作以外的日子,我希望能夠有一台 Server 讓我搞一些小玩意,那我該怎麼辦。

      通常大家會推薦 Share Web Hosting。但是仔細想想我們對 Share Web Hosting 第一個印象是什麼?大家一起用一台 Apache,一起用一台 MySQL,好擠呀。想用啥新服務不行,要等公司覺得有商業立基再說,好煩呀。想開個其他 PORT 來跑東西,不行。想幹嘛...不行,不行,不行。敝公司覺得你想要搞垮我們,所以你不可以。充其量,這些 Share Web Hosting 公司只是為了一般不了解架站的大眾而服務。但是像我們這種可以獨立控制一台 Linux 的人,就是不爽。

      那 Dedicated Server 呢?我們看看 Godaddy 的價碼,最經濟方案 63.00美金一個月。嗯嗯恩....我爸不是李嘉誠,我們也不是要搞公司,也只好重重拿起廣告單,輕輕的放下。

      我們發現到市面上只有兩個選擇。很便宜的 Web Hosting 跟很貴的 Dedicated Server。可是中間有一個
      想要一台便宜又方便的 Server 玩玩
      的斷層。我們已經厭倦了 Web Hosting 的不自由,但是又沒有 Dedicated Server的需求。以前這樣的需求只能夠自己架站。但是架站的網路,電源,機房等等問題又讓我們卻步。我們是 RD ,我們想玩 Server ,但是不想碰硬體的東西。

      這時候 slicehost 這樣的 Virtual Private Server 服務就是我們的解藥,當你付錢給 slicehost 後,他會給你一台 Linux 機器讓你玩,你可以 ssh 進去,你有 Root 權限,你有獨立 IP,你擁有一整台機器可以玩,而且價錢是剛好坐落在 Web Hosting 跟 Dedicated Server 中間,等於你每個月花20~30美金的價碼請一個專職網管幫你管機器,什麼硬碟壞掉,CPU 燒掉,主機板進水等等事情都不用煩惱,你只需要寫你的程式即可。

      至於他還有很多優點

      第一個是 SliceHost 有 5種 Linux 可以自由選擇,Ubuntu,Gentoo,CentOS,Debian,Fedora,你可以自由的選擇你想要的 OS。而且這裡有一個小插曲,我一開始選錯了 OS ,本來想說要寄信給 SliceHost 公司請他們換 OS,沒想到他們提供了 rebuild slice 的功能,你可以線上就把你的 Server OS 換掉。而且這個功能等於是當你被破台的時候,還是可以重灌 OS。

      第二個是因為他是 Ruby on Rails 寫的後台。並且網頁提供一個 AJAX Term console mode,當你機器 reboot 的時候,你可以看到你的 Linux 正在重開的畫面,或是當你重灌 Linux 的時候,你可以看到目前重灌的進度,有你在機房修機器的 fu~~~(註1)

      第三個是 SliceHost 標榜不超賣,大家說 Performance 很不錯。

      價錢我是選擇 20美金一個月的方案,256MB Ram + 10G Storage + 100G Bandwith 很夠用了。而網路上面大家提到一個很重要的問題,大家說因為 SliceHost 太熱門了,申請要等快一個月的情況並沒有發生,我只等半天。

      註1
      這個 console mode 真的好有fu~~
      重灌畫面


      登入 console


      開機畫面Reboot 畫面


      6/20/2007

      300篇達成,版面大修

      這位客官,你沒走錯,為了慶祝本 Blog 邁向第三百篇文章,我在版面上作了很大幅度的改變。

      1. 搜尋改用 Google

      我發現到 Blogger Nav Bar 的搜尋真是爛到極點,所以我砍了 Blogger Nav Bar,並且在側邊欄直接呼叫外掛 Google 大神來幫我作搜尋,大家以後可以直接使用右邊的 Search Bar 來搜尋本站的文章。

      2. 版型大改

      版型改成我最喜歡的白底黑字,而特別的字就用紅色。除此之外我拿掉幾乎所有的 Blog 的小玩意,包含繼續閱讀,Tag Cloud...等等最 Javascript。這個動作的原因是因為我發現
      來看我的 Blog 的人,你們只是來看內容而已
      這個趨勢從 Google Analysis 就可以知道


      這是我某段時間流量的來源的統計圖,我們可以發現到超過一半以上的人是被 Google 大神抓進來,然後查到你想要的東西,走人。

      這個推論,也從本 Blog 黏度只有 2.09 個可以知道(註1),我的觀眾都是查詢資料,查完一兩個網頁之後走人,也不會逗留。

      就一般網頁的角度來說,我該做出一些事情來增加黏性呢,但是想想不對
      等等,幹嘛增加黏性呢?這是一件好事呀。
      因為我當初成立 本 Blog 的目標,就是一個知識為主的 Blog 。而上述現象代表我的 Blog 越來越 Wiki 化了,使用者看待這個 Blog 是一個已知識為主的網頁,而非一個閒聊的網頁。與其弄一堆拉哩佈達的東西讓大家傷眼睛,還不如砍掉所有無意義的部份,只留下最簡單的黑底白字 ,讓大家查詢的時候更加的快而迅速的查到相關的資料。這才是友善的對待顧客吧 。

      所以我改了版面,希望大家喜歡。

      註1
      黏度:點閱網頁/造訪數

      6/18/2007

      Textile,RedCloth,Vim

      Textile

      有在用 Instiki 的人就知道,他是使用 Textile 這種語法。當 Web 大流行之後,大家發現到 Web 當中的核心 HTML 語法,雖然設計的很有彈性,但是 HTML 實在不是為了方便人書寫而設計的,裡面格式相當的囉唆而且難以書寫閱讀。為了書寫方便,所以產生 Textile 這種 Light Weight Markup Language 語法。

      Textile 的使用方式就不再詳加介紹了,可以看看 Wikipedia的介紹 ,總之 Ruby on Rails 上面很多套件都相當友善的支援 Textile。




      Red Cloth

      剛剛說到 Ruby and Ruby on Rails 上面很多套件都支援 Textile,他們都是靠 RedCloth
      這個 Gem 來支援的。他是一個相當容易使用的 Ruby Plugin,安裝方式就是

      gem i redcloth

      而使用方式就是

      require ‘redcloth’
      html = ”strong text and emphasized text
      r = RedCloth.new(html)
      r.to_html

      如何,很容易看的懂吧。

      vim

      剛剛看到網路上面強者這篇 Editing Textile in VIM ,裡面介紹如何使用 Vim 來編輯 Textile,並且提供 Textile Syntax File [1]。要使用他首先得先把這個 text.vim 放到 /.vim/syntax/ 底下,再來>將 /.vim/filetype.vim 加入一行

      au BufNewFile,BufRead *.textile setf textile

      假設使用 vim 編輯副檔名為 textile 的檔案,例如 xxx.textile,你就會發現他已經 S#ntax Highlight 過了。

      註1 我的 Mirror


      6/17/2007

      用 JRuby 來連接 Oracle

      JRuby 為 Ruby on Rails 帶來的效果已經出現了。

      根據 這篇文章 ,裡面提到了Oracle在 MAC OS X 上面支援度相當的差勁。沒有 standard client 也沒有 standard Oracle C libraries,導致 MAC OS X 上面,用 Ruby 連結到 Oracle 是一個Painful Job。以前遇到這檔事情,大家只能摸摸鼻子,說聲「再加強」。但是現在有了萬能超人 JRuby ,我們交給 JDBC 來解決這檔事情。

      首先,按照 我說的方式安裝 JRuby 還有 ActiveRecord JDBC。我文章裡面裡面提到的是如何安裝 MySQL ,要改連接到 Oracle 也是同樣的方式。去 Oracle’s JDBC download page 
      下載 ojdbc14.jar ,放到 $JRuby_HOME/lib/ 下面或是 exportCLASSPATH=ojdbc14.jar。

      然後在 Config 這樣設定即可
      production:
      adapter: 'jdbc'
      driver: 'oracle.jdbc.driver.OracleDriver'
      url: 'jdbc:oracle:thin:@server:1521:database'
      username: 'username'
      password: 'password'

      哈哈哈,Oracle 可以忽略 MAC 上面的用戶,可以忽略 Ruby 的用戶,但是他不能忽略 JAVA 上面的用戶呀,有了 JRuby 真是太美好了。

      6/15/2007

      JRuby 的未來


      右邊這張圖是從 JRuby 老大Charles Nutter 的 Blog 裡面 Copy 過來的(註1)。象徵的意涵是 Java Programmer 面對目前 Java 當前的問題,拼了老命尋找解法,卻發現他們找到了 Ruby 這個發光的寶石。

      言歸正傳,JRuby 當初發展到 1.0 的目標就是 Ruby compatibility,而且似乎也已經達成了。而 JRuby 未來的路要怎麼走呢?


      JRuby 的主要開發者 Charles Nutter 也早就明示
      1. 繼續加強速度
      2. Java Integration加強,1.1 可能會重寫整個 Lib
      3. 支援 Ruby 2.0 還有 Rubinius 產生的 Bytecode
      無獨有偶,Ola Bini 在接受 InfoQ 訪問時也提到未來 JRuby 走向
      1. 效能加強
      2. 正確性加強
      3. Java Integration加強
      4. Java ByteCode Compiler
      也就是說,效能正確性,跟 Java 整合度,以及 ByteCode Compiler 是未來 JRuby 努力的目標。

      關於 JRuby 未來的 core team 部分,繼 JRuby 兩個作者接受了 SUN 的 offer ,全職工作 JRuby 之後的九個月,Ola Bini 也接受了 ThoughtWorks 的全職工作,性質也是付錢給他開發 JRuby core。JRuby 已經完全顛覆了以往 Open Source 開發者做公益的宿命,三個主要開發者都有人付錢請他們開發。

      Ola Bini 上個月提到,JRuby又加入了兩個新的 core team member,Marcin Mielżyński 和 Bill Dortch。顯然 JRuby 社群是相當活躍的, 而且商業力量也一直進駐,他的開發速度怎麼看都覺得會繼續狂飆。

      JRuby 這東西前途不可限量。

      註 1
      我找不到圖片的 License,只好著名出處,有版權問題請告知。

      6/13/2007

      Leopard 立志成為最好的 Ruby on Rails 開發平台

      蘋果自從發現到 Ruby on Rails 使用者有一大部分都是使用 MAC 之後,開始在 OS 上面狂推猛推用力推 Ruby on Rails。到底蘋果支援到什麼程度呢?看看這一頁吧,未來的 OSX 10.5 Leopard 會直接 Boundle 進去 Ruby 1.8.6,Rails ,Mongrel,Capistrano 。


      Scripting Bridge.

      Mac OS X is now the ideal platform for all kinds of script-based development. Ruby 1.8.6 and Python 2.5 are both first-class languages for Mac development, thanks to Cocoa bridges, Xcode and Interface Builder support, DTrace monitoring, and Framework builds — plus AppleEvent bindings via the new Scripting Bridge. Leopard is also the premier platform for Ruby on Rails development, thanks to Rails, Mongrel, and Capistrano bundling.

      聽起來真的很美好,蘋果擁有偉大的 TextMate Editor,跟完全 Native Bundling 的 Ruby on Rails 全套 Package,再加上漂亮的介面,讓我一定會乖乖的掏出錢來買 Leopard。唯一的問題就是,Leopard 到底何時出呢?

      6/10/2007

      vim 上面使用 ruby 的方式

      最近聽到有人在問 vim 上面怎麼使用 ruby,尤其是怎麼縮排的問題,我在這邊稍微提一下怎麼用。其實 vim 的設計就是使用 configuration 來做到支援不同語言,但是撰寫 vim 設定檔其實不是一件很簡單的事情,所以才有 vim-ruby 的存在。vim-ruby 是一個 gem package,只要使用他就可以幫你簡單的做好 vim 上面對 ruby 的支援。


      安裝 vim-ruby
      gem i vim-ruby

      安裝 vim-ruby configuration file
      vim-ruby 有附一支 ruby script ,叫做 vim-ruby-install.rb,在安裝 vim-ruby gems 之後,你的路徑下面就會出現這隻 script ,請打入
      vim-ruby-install.rb
      幫助你自動的把相關的 Syntax ,indent config 檔案放到相關的目錄下。以下就是他會出現的選項
      Possible Vim installation directories:
      1) /home/wisely/.vim
      2) /usr/share/vim/vimfiles
      第一個是在講說,將相關 vim-ruby config 安裝在自己目錄下面,只有自己可以使用。第二個就是放在系統的 vim config 下面,不過你當時的權限要 root 才能安裝。原則上兩個都可以啦。

      不能縮排的解法

      本來這樣的步驟,在我 notebook 上面這樣就可以完全無誤的使用了。但是當我最近新裝另外一台機器的時候,我發現裝好 vim-ruby 之後,很奇怪的 vim 有 syntax highlight,但是卻沒有程式碼縮排。

      後來我發現到,只要將我 notebook 上面的 .vimrc 放到新裝的機器上面即可做到縮排,所以
      問題不在於 vim-ruby,而是沒有適當的 .vimrc
      雖然用 vim 很久了,但是依舊沒有很深入的去了解怎麼去設定,真是很慚愧。不管怎麼說,我先將我的 .vimrc 放上網路,大家確認一下是否可以使用。這隻 .vimrc 陪我征戰大江南北,目前為止還不錯用。

      UPDATE:

      根據網友提醒,Ruby on Rails Wiki 網頁有講到只要在 .vimrc 裡面加入
      set nocompatible " We're running Vim, not Vi!
      syntax on " Enable syntax highlighting
      filetype plugin indent on " Enable filetype-specific indenting and plugins

      " Load matchit (% to bounce from do to end, etc.)
      runtime! macros/matchit.vim

      augroup myfiletypes
      " Clear old autocmds in group
      autocmd!
      " autoindent with two spaces, always expand tabs
      autocmd FileType ruby,eruby,yaml set ai sw=2 sts=2 et
      augroup END
      這些即可。

      6/08/2007

      JRuby on Rails 安裝方式

      有了號稱可以跑 Rails 的 JRuby ,當然要來試試看 JRuby on Rails 怎麼安裝。因為我的 test 機器上面已經有裝好原先的 Ruby 跟 Rails ,所以我們就每個指令都打全部的執行檔路徑避免搞混。本 Tutorial 在 Linux 上面測試成功。



      安裝 Rails

      JRuby 有附帶一個 gems 在 $JRuby_PATH/bin/ 底下。我們使用我們最熟悉的方式來裝,就是 gem 安裝
      $JRuby_PATH/bin/gem i rails -y
      他會安裝 Rails package 到 $JRuby_PATH/lib/ruby/gems/1.8/gems/ 底下。以後所有的 JRuby Gems 都會安裝到這個下面。安裝好了後,$JRuby_PATH/bin/ 會多出 rails 這個指令,這個就是我們熟悉的 rails command。

      安裝 MySQL JDBC Driver

      因為 JRuby 不能裝我們熟悉的 ruby-mysql,所以使用 JDBC 來操作 MySQL。你可以到任何地方去安裝 MySQL JDBC Driver 的 jar 檔案,但是如果不知道那裡抓的話,可以試試看 MySQL 官方的 Connector/J 。然後 mysql-connector-java.jar 檔案放到 $JRuby_HOME/lib/ 底下。(註1)

      安裝 ActiveRecord-JDBC

      這是 Active Record 跟 JDBC 的介面,用 gem 來安裝
      $JRuby_PATH/bin/gem i ActiveRecord-JDBC
      安裝好了之後就可以使用 JDBC 來 Connection MySQL。

      新增 Rails APP
      熟悉的指令來了,只是請確定你是使用 JRuby 的 rails 來新增 Rails App
      $JRuby_HOME/bin/rails app_name
      修改 Enviroment config
      rails 的 config/enviroment.rb 要稍微修改
      Rails::Initializer.run do |config|
      end
      裡面要加上
      RAILS_CONNECTION_ADAPTERS = 'jdbc'
      這句,不然會出現 error。(註2)

      Database config 修改

      因為改成 JDBC 了,所以 config/database.yml 也會改成
      development:
      __adapter: jdbc
      __driver: com.mysql.jdbc.Driver
      __url: jdbc:mysql://localhost:3306/資料庫名稱
      __username: root
      __password:
      這個樣子的設定方式,原先的 database 選項是無效的,必須放在 url 選項的最後面才可以使用。

      啟動 Rails Server

      終於要啟動了,啟動方式就是
      jruby script/server
      他會啟動 webrick 。

      註1
      我試過 $CLASSPATH 的方式,但是無法還是無法正確 connection ,會出現以下 error
      The driver encountered an error: cannot load Java class com.mysql.jdbc.Driver
      所以我採用這個方式。

      註2
      當沒有寫入 config/enviroment.rb ,啟動時會出現下列 error
      > jruby script/server
      => Booting WEBrick...
      /home/wisely/jruby-1.0/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/connection_adapters/abstract/connection_specification.rb:209:in `establish_connection': database configuration specifies nonexistent jdbc adapter (ActiveRecord::AdapterNotFound)

      JRuby 安裝方式

      JRuby 1.0 出了,我們開始看看怎麼安裝吧,這裡先測試 Linux 上面安裝方式。



      前置動作

      你的系統必須安裝好
      • Java 1.4 以上
      • Ant
      下載 JRuby Source

      你可以到官方下載區,或是我的 Mirror 下載 Source Package。將他解壓縮。

      Compile JRuby

      他有 bin 的版本的,不過我還是喜歡 compile 。只要有系統有 ant,我們直接打
      > ant
      即可 compile。

      執行檔路徑指定

      jruby 的執行檔在 ./bin/jruby 下面,請將 PATH 路徑指到這裡。並且確定你的 JAVA_HOME 變數沒錯。
      > PATH=$PATH:/你的/jruby/根目錄/bin
      > JAVA_HOME=/你的/java/根目錄
      這樣以後執行 jruby gem 才沒有問題。

      測試看看

      指定好目錄後,直接打
      > jruby -v
      ruby 1.8.5 (2007-06-08 rev 3841) [i386-jruby1.0]
      看看有沒有問題。

      執行第一支 JRuby 程式

      寫一支簡單的 Ruby 程式,這裡採用之前 JRuby 代表的意義範例 code。
      require 'java'
      include_class 'java.util.Random'
      r = Random.new(123)
      puts "Some random number #{r.nextInt % 10}"
      r.seed = 456
      puts "Another random number #{r.nextInt % 10}"
      然後來測試
      > jruby random.rb
      Some random number 9
      Another random number 0
      呵呵,成功了。

      JRuby 1.0 Release

      雖然官網還沒有講,不過 Download 區已經有了1.0版了。將將將,Ruby 有始以來最受期待的 VM
      JRuby 1.0 Release 啦~~~~~~~
      我這裡為台灣地區 Mirror 一下檔案,這是 src 檔案,這是 bin 檔案。接下來的幾天,每天都要開始介紹 JRuby 的題目歐。

      6/04/2007

      在 CentOS 安裝 Ruby on Rails

      昨天在 CentOS 安裝 Ruby on Rails 的時候,我發現到雖然用 RubyWorks 來安裝很快,但是有些小細節還是得注意。所以還是寫一個 Tutorial 好了。



      1. 安裝 RubyWorks

      安裝 RubyWorks Repo
      wget http://rubyworks.rubyforge.org/public_key.txt
      sudo rpm --import public_key.txt
      wget http://rubyworks.rubyforge.org/RubyWorks.repo
      cp RubyWorks.repo /etc/yum.repos.d/
      用 yum 安裝 RubyWorks
      yum install rubyworks
      安裝好 RubyWorks ,他會把 ruby,rubygems,Mongrel,Haproxy,Monit 安裝跟設定好。但是他不會安裝 Rails ,而是 copy 一份 Rails 在 /usr/rails 上面,這其實是很正確的作法,因為他一開始就取向 Production Server,而 Production Server 本來就該將 Rails 版本 Freeze 在 Rails Doc 裡面。但是如果還是要在 CentOS 安裝 Rails Gem,那就
      gem i rails -y
      即可。

      2. 安裝 MySQL

      RubyWorks 好歸好,就是沒有選擇讓我們裝 DB Server,我們這裡就直接用 yum 安裝 MySQL
      yum install mysql-server

      3. 安裝 Ruby MySQL Native Lib

      我發現到 RubyWorks 並不會安裝 Ruby MySQL Native Lib,所以我們得用 gem 安裝,但是又發現 centos 上面安裝 MySQL Gem 會出現這樣的錯誤訊息,網路上也有人在 complian
      checking for mysql_query() in -lmysqlclient… no
      checking for main() in -lm… yes
      checking for mysql_query() in -lmysqlclient… no
      checking for main() in -lz… yes
      checking for mysql_query() in -lmysqlclient… no
      checking for main() in -lsocket… no
      checking for mysql_query() in -lmysqlclient… no
      checking for main() in -lnsl… yes
      checking for mysql_query() in -lmysqlclient… no
      *** extconf.rb failed ***
      Could not create Makefile due to some reason, probably lack of
      necessary libraries and/or headers. Check the mkmf.log file for more
      details. You may need configuration options.
      Provided configuration options:
      –with-opt-dir

      所以得先 remove MySQL 然後再重新安裝 MySQL 跟 MySQL Development Lib
      yum remove mysql
      yum install mysql
      yum install mysql-devel
      gem install mysql
      至於為何這樣,我也不太清楚。反正 work 就好啦。

      這樣應該就安裝完成了。

      JRuby ,Ruby 界的救世主?

      今天早上看到 ericsk’s blog 的 JRuby 1.0 開始倒數,就回去看 Charles Nutter 的原文 JRuby 1.0.0RC3 Released - And This Is It!,我發現到 JRuby 很多東西真的很值得一提。


      1. JRuby 1.0 這周上市

      6/3 JRuby 1.0 RC3 發佈,1.0 Release 也將在這周發表,他將是 Ruby 1.8.5 compatible 的。
      The only things that will change from now until a 1.0 final release later this week would be any showstopping bugs that are extremely low-impact to fix. In general, RC3 should be nearly identical to 1.0 final.
      2. 效率不錯,並且會引進 JIT

      JRuby 1.0 會有 JIT Compiler ,代表可以 compile ruby code,並且大多數的時候可以跑得比一般 Ruby 1.8 快。 Rails 用 JRuby 跑在 Java Application Server 上面的效果一般來說很不賴。但是因為 JRuby 1.0 之前主打的是跟 Java 的整合度,所以可以作的事情還有很多。

      We've had anecdotal reports that JRuby on Rails in a Java application server performance extremely well, and other reports that general Ruby applications perform somewhat poorly. The general performance situation is not well-understood, but we all agree there's a lot more work to be done.

      3. 跟 Java 整合不錯,但是可以再加強

      大部份的時間 call lib 跟 繼承 class 都沒太多問題,不過有些 case 還是沒搞定。這個問題將會在 JRuby 1.1 的時候,以重新 Design Lib 的方式來解決。

      基本上其他的東西就不提了,光是 JRuby 1.0 可以跑 Rails 跟可以 JIT Compile 就值得大書特書了。如果實做的沒有太大的問題的話,說不定是下一個 Ruby 跟 Rails 的高峰。

      6/03/2007

      Rails 2.0 預計的新特色

      Ruby on Rails 作者 DHH 在 Rails Conf 2007 主題演講 A peak at Rails 2.0,裡面提到很多 Rails 2.0 預計有的新功能,大致上還是走「加強 REST ,修改許多細節,尤其是 performance 」的方向走,現在我們就來 check 一下吧。由於投影片沒有講得很清楚,我也順便看了 Robbin 的 railsconf2007大会介绍




      更好的 REST 支援
      • ActiveResource 正式 release ,不再只能去 check svn 來 download
      • 有了更輕巧的 REST , Action Web Service 要移出 Rails Core
      • HTTP Basic Auth 支援,解決 REST 對於 Auth 的問題
      • respond_to 可以直接輸出 RJS
      • 更強大的 mine_type


      更好的 performance

      最大的消息就是有 query cache 可以用了。並且他加了不少 static file 處理的強化技巧。可以用
      <%= javascript_include_tag :all , :cache => true %>
      <%= stylesheet_include_tag :all , :cache => true %>
      自動合併以及壓縮一些 css 或是 js static file,順便下 cache。

      而且可以在 config 裡面設置
      config.action_controller.asset_host = 'static%d.example.com'
      讓 images ,js,css 的 render 出來的路徑變成
      <img src="static1.example.com">
      <img src="static2.example.com">
      類似這樣的形式,可以簡單的將 static file 分離到 static server。


      更簡單的 Migration

      你很討厭寫 t.column 嗎?現在,你可以這樣寫
      create_table :people do |t| 
      t.first_name :type=>:string
      ...
      end
      以及
      create_table :people do |t| 
      t.string :first_name
      ...
      end
      後者更勝一籌。

      一些小細節

      Breakpoint 回來啦。可以在啟動 Rails 的時候,將初始化動作寫到 initializers 裡面。

      這裡是這個投影片


      6/01/2007

      Fedora 7 安裝 Ruby on Rails

      全新燒燙燙的 Fedora7 出來了,當然開始 test 他對 Ruby on Rails 有沒有問題啦(其實只是我愛好安裝新版本 Linux)。我最近發現到 Red Hat 系列對 Ruby on Rails 的支援度真是好,真的還蠻心動的。現在我們一個一個手動安裝吧。




      前置動作
      就是以下的動作是對於整個過程有幫助,但是不一定要做的方式。
      1. 修改 yum server ,指到國內義守的 server
      vi /etc/yum.repos.d/fedora.repo
      baseurl 改成
      baseurl=http://ftp.isu.edu.tw/pub/Linux/Fedora/linux/core/$releasever/$basearch/os/

      vi /etc/yum.repos.d/fedora-updates.repo
      baseurl 改成 baseurl=http://ftp.isu.edu.tw/pub/Linux/Fedora/linux/core/updates/$releasever/$basearch/

      2. 安裝 gcc complier
      請打 gcc ,看你有沒有裝好 gcc compiler ,如果沒有的話,我們用暴力一點的方式
      yum install gcc*
      3. 安裝 MySQL
      yum install mysql-server
      開始安裝
      1. 安裝 Ruby 以及 Ruby 的 MySQL Driver
      yum install ruby ruby-libs ruby-devel ruby-rdoc ruby-mysql ruby-irb
      2. 安裝 Ruby Gems
      太棒了,Ruby gems 也是內建就有的
      yum install rubygems
      3. 安裝 Rails
      gem i rails -y
      4. 安裝 Mongrel
      如果沒裝 gcc ,這裡會失敗
      gem i mongrel
      心得
      Fedora7 安裝 Ruby on Rails 真的很方便,已經全部整合到 yum 裡面了,要快速架設 Server 應該不是任何問題。

      同場加映,Lighttpd + Fastcgi 安裝方式
      安裝 fastcgi 
      wget http://www.fastcgi.com/dist/fcgi-2.4.0.tar.gz
      cd fcgi-2.4.0
      ./configure
      make
      sudo make install


      Ruby Fastcgi
      wget http://www.moonwolf.com/ruby/archive/ruby-fcgi-0.8.7.tar.gz
      ruby install.rb config -- --with-fcgi-include=/usr/local/include --with-fcgi-lib=/usr/local/lib
      ruby install.rb setup
      ruby install.rb install


      5/31/2007

      Markaby:惡趣味的逆襲

      有些東西你明知道是錯的,但是還是會去做,只是因為那樣做很爽。

      不是說你很邪惡,而只是因為有時候作壞事本身就是一件很有趣的事情。像是蹺課出去打撞球,像是上班偷懶,像是捉弄朋友....等等雖然明知道本身是不對的事情,但是依舊無法抗拒這種快感。第一次看到 Markaby,心中的 OS 是「妖孽呀,這是網頁設計的邪道呀」。但是最近有機會碰到高手寫的 Markaby code ,頓時發覺有點沈溺其中無法自拔(果然是邪道,才會有毒品的快感)。或許這又是一個明知不對,但是又令人忍不住去碰的小誘惑。

      敝人小弟在下我曾經寫過HTML?New Template System ?,裡面有提到
      Ruby 統一全世界當然是一個美好的夢想,畢竟我是100%原汁的 Ruby 派。但是當你在商業應用上,版面設計通常交給美工,他們只需要會 Dreamweaver 之類的東西
      這時候,難道你要教美工 Ruby 程式設計?
      所以,除非 Dreamweaver 或是 Frontpage 支援 Ruby @@!,不然大家還是先把 HTML 當成網頁程式設計的最大公約數好了。
      因為考慮到美工人員不太會去管程式,程式也沒這個 sense 去碰美工,所以所謂的 template 正道,就是「美工歸美工,程式歸程式」。基本要求是 HTML 版面跟 Rails 程式分開,美工好做事,程式也好修改。

      但是 Markaby 就是一個相當詭異的存在,他是一個使用 Ruby Code 來撰寫 html 的方式。他是一個 Rails Plugin ,安裝方式是
       script/plugin install http://code.whytheluckystiff.net/svn/markaby/trunk
      rhtml 跟 markaby 是可以兩者並行的,請先將你的 markaby file 都從 .rhtml 改成 .mab 的名字,這樣 rails 就可以知道這是 markaby 的檔案了。

      撰寫範例是這樣

      h1 'Listing products'

      table.editor.classic do
      tr do
      for column in Product.content_columns
      th column.human_name
      end
      end

      for product in @products
      tr do
      for column in Product.content_columns
      td product.send(column.name)
      end
      td { link_to 'Show', :action => 'show', :id => product }
      td { link_to 'Edit', :action => 'edit', :id => product }
      td { link_to 'Destroy', { :action => 'destroy', :id => product }, :confirm => 'Are you sure?' }
      end
      end
      end

      link_to 'Previous page', { :page => @product_pages.current.previous } if @product_pages.current.previous
      link_to 'Next page', { :page => @product_pages.current.next } if @product_pages.current.next

      br

      link_to 'New product', :action => 'new'
      裡面有很多 html tag 跟 Ruby code,Rails helper。裡面看不到煩人的 <% %> 等符號,只有讓人興奮的 Ruby code。

      好處呢?

      就是一個爽字形容,還有另外一種自己已經成為高手的錯覺。

      壞處呢?

      你沒辦法用美工改好給你的 HTML code ,你必須要求美工使用 CSS 來做所有排版的工作,不然合作起來也非常累。另外一個壞處是,交接的時候交接的人會很不高興,這是哪門子的版面 code ,要我怎麼看呀。

      該不該用呢?

      就實際面來說,沒有任何實用價值。但是你也知道,有些東西你明知道是錯的,但是還是會去做,只是因為他很爽。所以夜深人靜的某個夜晚,我依舊偷偷使用 Markaby 來寫我的某個小網頁 :p

      5/28/2007

      給寄信問我問題的朋友們

      我先說一下我現在 Email inbox 裡面的情況,我每天會收到 10 ~ 50封左右的問 Ruby on Rails 問題 Email,x 封左右的 Start up 合作信件,還不包含我工作相關信件。也就是說,你們寄給我的信件通常會在Email 大海中飄盪,運氣好我會看到,而且就算看到了,我通常抽不出時間解決。最慘的是,通常 10個問題有五個是重複的....................。

      這個情況已經持續了三個月有了,我也不知道為了晚回 Email 道歉過幾百次了,為了解決這個情況,希望每個看我 Blog 朋友,如果有問題的話,可以到 JavaWorld 的 Ruby 版上面發問,我會定期去那邊回答問題的,非常感謝。


      Event Driven Mongrel

      Mongrel 就大家所知道的,是採取 Thread 的方式來運作的,但是multi thread 在concurrent 大時 loading 會很重,要花很多時間處理很多 thread sync 問題。所以現在很多 Web Server ,包含 Lighty,Zeus 都是採用 Event Driven 的方式來實做,Apache 現在也有 Event Driven 的運作方式。

      Mongrel 現在也有人做 Event Driven 的實做方式了,不過你得跟 Swiftiply 一起安裝。

      gem i swiftiply

      然後啟動 Mongrel 就始用

      EVENT=1 mongrel_rails start

      就可以啟動了。

      快不快的部份我現在還沒發現,但是至少跑到現在還沒掛點是個很好的事情。


      5/23/2007

      [ 書評 ] Ruby on Rails 專業網站案例實作


      對於我這樣不認真的人來說,要我寫 Testing 簡直是要了我的命,所以我從一開始看 Ruby on Rails 的時候,就完全沒碰 Testing 的部份。上次 UbiSunrise 的活動結束後,我還記得有觀眾告訴我

      Ruby on Rails 比 Java 好的地方就是 Testing

      讓我霎時間一個大大的 shock 。到底 Ruby on Rails 的 Testing 有何精妙之處呢?






      命運是好玩的,很快的這本 「Ruby on Rails 專業網站案例實作」就出現在我的身邊。這是 Beginning Ruby on Rails E-Commerce: From Novice to Professional 的翻譯本,從書名來看,這本書是介紹用 Ruby on Rails 來寫 E-Commerce 的書,但是翻到一半,他給了我一種「Beyound Java」的感覺,沒錯,又是一本內容不錯,但是書名取怪的書。如果要我重新定一個書名,我想取「使用 Ruby on Rails學習 Test-Driven Development」應該是一個很好的書名。

      沒錯,這是一本講解 Test-Driven Development 的良好教材,應該說,裡面有很多很棒的 Ruby on Rails Testing 範例 Code。並且開發方式真的是遵照 TDD 原則,先寫 Testing code ,再開始寫 real code。我從裡面的範例從頭到尾看到完,我享受了一頓真的很不錯的 Testing Tutorial。我從裡面學習很多很多 Testing 的技巧跟觀念。書的後半段還有介紹 Selenium 這個驗收測試的工具使用方式。真的是 Testing 的全套都 run 過一次,整本書算是一個完整的 Testing Tutorial。

      再來,最後面的部份其實收錄了不少 Enterprise 才需要的問題,像是 deploy,I18n,效能最佳化等等的議題,而且整理的還很不錯。

      最後,翻譯者功力很好,翻譯的不差,我那麼討厭看中文電腦書的人都覺得翻譯的真的順眼。「Convention over Configuration」 翻成「慣例優於組態」這個翻譯是我看過目前為止,把 Convention over Configuration 翻譯的最簡短,也最不失真的翻譯方式。

      要講缺點的話,當然也有。他不是一個初學者的書本,裡面的講解方式都是要對 Ruby on Rails 有一定基礎的人才能夠輕鬆的閱讀,講解基礎觀念的部份不多。再來就是書名很容易造成誤導,最好改個書名比較好。

      我還蠻喜歡這本書的。


      5/17/2007

      把你的 Rails App 打包成 RPM Package

      剛剛看到 gigix 寫的 Create RPM For Your Rails Application,這是一個叫做 rpmpackager 的 rails plugin,目的是將你的 Rails App 打包成 RPM Package。我覺得這個東西假設配合 RubyWorks ,是一個在 Fedora Like Linux 上面還算是不錯的 deploy 的好作法。






      前置工作

      在使用這個 plugin 之前,系統上面必須安裝而且設定好 rpmbuild 這個工具。

      安裝 plugin

      ruby script/plugin install http://rubyworks.googlecode.com/svn/trunk/rpmpackager/

      設定

      設定檔在 vendor/plugins/rpmpackager/config.yml 裡面,內容是

      configuration:
      app_name: app的名字
      description: 敘述
      license: Apache
      version: 1.2.1
      release: 1
      # RPM dependencies. separated with commas dependencies: openssl, mysql >= 5.0
      # 這裡敘述著 RPM 之間的 dependencies
      # 如果我要使用 openssl 跟 MySQL 5.0 以上的版本,就這樣寫
      # openssl, mysql>=5.0
      # 中間用 , 分開
      # gem dependencies and installation indecies
      # 0 for gems don't need selection
      # gem 之間的 dependencies ,0 代表不用,1 代表需要這個 gem package
      gems:
      redcloth: 0
      rcov: 1

      打包 RPM

      使用 rake rpm_package 來打包成 RPM ,他會將 RPM Package 放在 /usr/src/redhat/RPMS/i386/ 底下。而打包好的 RPM 會自動安裝到 /usr/local/lib/rails-apps/#{app_name} 底下。


      RubyWorks 0.0.1 Release

      如果你覺得安裝所有的 Ruby on Rails 相關套件,並且將 Production Server系統設定好是一件很麻煩的事情嗎?或許你可以試試看 RubyWorks

      RubyWorks 是一個在 Red Hat Enterprise 或是 CentOS 上面的套件組合,他會幫你把所有 Production 環境下面的相關的 Ruby on Rails 套件跟 Server 套件一次安裝完成,並且提供一個馬上可以跑的 defulat config file,也就是說各位公司的技術長們不需要花時間去看那麼多 Production 設定方式,你已經有一個很堪用的 Production Ruby on Rails Server了。

      So,你還有理由不玩 Ruby on Rails嗎?

      我們看看怎麼安裝 RubyWorks,因為我沒有 Red Hat Enterprise Server,所以我只 Test CentOS。

      前置作業

      RubyWorks 因為好像還沒進去 yum 資料庫,所以我們還是得必須告訴 yum 哪裡有 RubyWorks 的 Package,如果已經進去yum repo了,就好像不需要這個動作了。

      如果你像我一樣,是個不求甚解,只求可以 Work 的人,就這樣打就好了。
      wget http://rubyworks.rubyforge.org/public_key.txt
      sudo rpm --import public_key.txt
      wget http://rubyworks.rubyforge.org/RubyWorks.repo
      cp RubyWorks.repo /etc/yum.repos.d/

      YUM 安裝 Ruby Works
      直接用 gem 安裝
      yum install rubyworks
      然後.....裝好了。

      請連線到 http://localhost:3001/ 的地方,你一定會看到一個很熟悉的畫面。是的,Ruby on Rails 已經跑起來了,還是用 Haproxy 幫你跑的。不過這裡要講的是,因為他的取向不是 development server,而是 production server,所以他並不會安裝 Rails 的 gem package,而是直接將 rails 放在 /usr/rails/vender/rails 裡面。

      Rubyworks 安裝表

      RubyWorks 一共會幫你安裝
      • ruby
      • ruby-devel
      • rubygems
      • haproxy
      • monit
      • mongrel
      • rubyworks
      並且幫你設定好 HAProxy ,跑在 3001 Port,Mongrel 跑在 3002~3005 Port,monit 跑在 2812 port。

      Rubyworks 詳細位置表

      詳細的安裝位置是在
      1. /usr/bin/ruby/:Ruby 所在地
      2. /usr/lib/ruby/ :Ruby libraries
      3. /usr/lib/ruby/1.8/ :Ruby standard library
      4. /usr/lib/ruby/gems/1.8/gems/ :所有安裝的 Ruby gems Package
      5. /usr/bin/monit :monit 執行檔
      6. /etc/init.d/monit:monit的啟動 script,所有的 server 都會在 monit 啟動的時候,也順便幫你啟動好了(Mongrel,Haproxy)
      7. /usr/bin/haproxy :HAProxy 執行檔
      8. /usr/bin/mongrel_rails :Mongrel
      9. /etc/rails/ :configuration files
      10. /var/rails/ :所有 Deamon 的 .pid files
      11. /usr/rails/ :Rails app code 所在地。
      12. /var/log/monit.log :Monit 的 log
      13. /var/log/haproxy.log :HAProxy log
      14. /usr/rails/log/:Mongrels and Rails 的 log

      延伸閱讀

      5/15/2007

      心愛的 Object 變心啦

      剛剛發現一個很有趣的事情,寫 code 的時候,有兩個 Model :Person 跟 Setting ,他們呈現 1: 1 關係。結果當我想要創立一個新的 Person 的時候,為了希望能夠簡化設計,我就將其中一個人 a 當作預設值,每個新增 Person 的 Setting 直接 copy 一份過去,所以我就這樣寫




      a = Person.find(1)
      b = Person.new( :name => 'lala' )
      b.setting = a.setting
      b.save

      我真的沒想太多,但是慘劇就發生了。a.setting 就變心到 b 去了。

      >> a = User.find 1
      => #<Person:0x371ee38 @attributes={"updated_at"=>"2007-05-15 22:55:45", "nname"=>"hemidemi lala", "type"=>"GroupAdmin", "id"=>"1", "password"=>"123", "created_at"=>"2007-05-09 00:46:35"}>
      >> a.setting
      => nil

      也就是他自動的幫你把 a.setting 的 model 裡面的 foreign key 指定到新增的 b ,然後一去不回頭。要預防 object 變心方法也很簡單,就是幫新人找一份完全一模一樣的新伴侶即可。

      a = Person.find(1)
      b = Person.new( :name => 'lala' )
      b.setting = a.setting.clone
      b.save

      Clone 是 Ruby object 裡面的 method ,作法就是 copy 一份新的 instance。雖然在實際使用上, 其實 clone 並不會直接 new 一份真的 instance,而是 new 一個 object ,然後將裡面 attribute 直接 reference 過去[註1]。但是在 ActiveRecord 裡面使用,因為是直接寫回資料庫,所以就完全沒副作用,所以可以盡量大方的使用。

      註1

      irb(main):001:0> class Klass
      irb(main):002:1> attr_accessor :str
      irb(main):003:1> end
      irb(main):004:0> s1 = Klass.new => #<Klass:0x89e7c>
      irb(main):007:0> s1.str = 'Hello' => "Hello"
      irb(main):008:0> s2 = s1.clone => #<Klass:0x79d38 @str="Hello">
      irb(main):009:0> s1.object_id => 282430
      irb(main):010:0> s2.object_id => 249500
      irb(main):011:0> s1.str.object_id => 261360
      irb(main):012:0> s2.str.object_id => 261360

      我們可以發現到 s1 跟 s2 其實是兩個不同的 object ,但是裡面的 attribute str 卻是同一個 object。