少就是多) Ruby on Rails 簡介

知名的 Web design 線上雜誌 A List apart No.257期少見地刊出 Rails 入門介紹,心血來潮來做翻譯,斷斷續續翻潤了好幾次,覺得文章看起來沒什麼,翻起來好長啊。
終於再度體會 text.plain 果然是最難寫的格式。寫投影片,做翻譯比寫程式還辛苦…orz

以下翻譯自 Creating More Using Less Effort with Ruby on Rails by MICHAEL SLATER

如果你開發網站,想必應該聽過 Ruby on Rails (RoR) 的大名。但是如果是網頁設計師或前端工程師,或除了PHP沒有用過其他框架,那麼採用 Ruby on Rails 方案似乎會是一個很大的改變。在這篇文章中,我希望能夠除去 Ruby on Rails 神秘的面紗,並說服你採取行動,這將會非常值得如果你的需求符合下述的 Ruby on Rails 甜蜜點。

學新方法去做本來就會做的事情,還要同時學新觀念和新技巧,確實會花你一點時間。直接了當地說,即使是 Ruby on Rails,轉換技術都將會摧毀你的生產力。然而,我相信網站開發者如果開始採用 Ruby on Rails,將變得更有生產力做出更好的網站,以及從中獲得更多的樂趣。

Rails樂趣

Ruby on Rails(簡稱Rails)是一個完整的框架,意思是說他包含了前端跟後端。它讓 “要做多種不同工作的人” 開發者能擁有極強有力的工具。即使基本上你只是前端或後端工程師,你仍可以有效率的使用 Ruby on Rails。我們可以清楚定義前端(瀏覽器HTML、CSS和JavaScript)和後端(Ruby和Rails框架)的介面,所以如果你只想要專注在其中一端的話,不需要全盤了解。

如果你是網頁設計師或前端工程師,你會學到如何使用 Ruby on Rails 樣板系統,而且學一點內嵌Ruby程式碼在 View 檔案。這將讓你成為後端開發者更好的夥伴,因為你可以直接操作 Rails 應用程式,而不是讓某人去整合HTML和CSS。

因此無論你用前端或後端工程師的角度採用 Ruby on Rails,可以想想看有哪些專案可以考慮採用?

閱讀全文〈少就是多) Ruby on Rails 簡介〉

使用 Passenger (a.k.a mod_rails) 當做開發環境

Update(2008/6/25): 提昇 MacOS 開發爽度請裝 Pane Putting the pane back into deployment

Update(2008/5/24): 更多參考連結 28 mod_rails / Passenger Resources To Help You Deploy Rails Applications Faster

mod_rails(學名是 Passenger) 出來一段時間了,陸續開始有些使用經驗分享出來,在 production 上還蠻適合RAM有限的 VPS 環境,而這篇 Ask Your Doctor About mod_rails則介紹 mod_rails 也十分適合拿來當做 development 環境,也讓我十分心動:

  1. 厭倦每次都得 mongral_rails start 或 script/server?而且還要佔 terminal tabs。像我手上同時間好幾個案子(?!),常常要切來切去還挺麻煩的。有了 mod_rails 設定好之後,每個網站都隨時 ready 可以用。(怕 memory 浪費?mod_rails 可以經由設定 RailsPoolIdleTime, RailsMaxPoolSize 來限制 process 存在的時間跟數量)
  2. 單一 mongrel process 沒辦法平行處理 requests,當網站圖片東西比較多的時候,速度就慢了。而 mod_rails 在有額外的 request 需求時,會 new process 來支援。
  3. 有 Apache 就可以設定 SSL,只用 mongrel 沒辦法測試 HTTPS 連線。

心動了當然得馬上行動,參考了這篇 Using Passenger on OSX for Rails development,我很順利地在我的 Mac Leopard 上架了起來:

1.安裝 Passenger:

gem install passenger
passenger-install-apache2-module

2.設定 Apache,編輯 /etc/apache2/httpd.conf 或 /etc/apache2/users/ihower.conf,以下是一個範例 (前三行請參考執行 passenger-install-apache2-module 時顯示的訊息) :


LoadModule passenger_module /opt/local/lib/ruby/gems/1.8/gems/passenger-2.0.1/ext/apache2/mod_passenger.so
PassengerRoot /opt/local/lib/ruby/gems/1.8/gems/passenger-2.0.1
PassengerRuby /opt/local/bin/ruby
PassengerMaxPoolSize 3
PassengerPoolIdleTime 300
RailsEnv development

<Directory "/Users/ihower/RailsCode">
Order allow,deny
Allow from all
</Directory>

NameVirtualHost *:80

<VirtualHost *:80>
DocumentRoot "/Users/ihower/RailsCode/project1/public"
ServerName project1.local
</VirtualHost>

<VirtualHost *:80>
DocumentRoot "/Users/ihower/RailsCode/project2/public"
ServerName project2.local
</VirtualHost>

  1. 設定 /etc/hosts 指定本地端 domain:

    127.0.0.1 project1.local
    127.0.0.1 project2.local

4.打開 Mac 上的 System Preferences ➔ Sharing ➔ Web Sharing,啟動 Apache。
5.打開你的瀏覽器,輸入 project1.local, project2.local 順利的話就可以看到啦。

問: 修改了 /vendor/ 下面的東西要重新載入怎麼辦?
答:mod_rails 的用法挺有趣的,請執行:

touch tmp/restart.txt

如果要一直修改 vendor 的話(在寫plugin嗎?),可以下載 Automation with RStakeout,然後執行:

ruby rstakeout.rb "touch tmp/restart.txt" "vendor/**/*"

這樣一有更動就會reload了,cool。

Github 分散式版本控制的殺手級應用

最近常常推薦人家去玩 Github,到底有用在哪裡? 就來寫一篇廣告文吧。

GitHub 是基於 Git 這套分散式版本控制系統的 Repository hosting 應用,一開始我也沒聽過 Git ,覺得用 Subversion 好好的為什麼這些人要換。抱著嚐鮮的念頭用了之後,發現實在好玩極了。目前已經有非常多的 Rails 相關應用都已經在上面進行開發,包括Ruby on Rails coreRSpecwill_paginate pluginattachment fu_plugin等等,幾乎所有我用到的 Rails plugins 在上面都可以找的到。

到底有那些特色呢?

  1. 你可以 watch 你所關注的專案,Github 提供 private RSS 訂閱。有了這個功能,我有用到的 plugins 的進度我都可以掌握。
  2. 可以看到哪個專案最多人 watch,比較哪個比較多人用(比較多人用比較保險?)。
  3. 你可以 follow 你所關注的開發者動態(例如ihower),看看又有什麼新的好東西 :p
  4. 你可以對專案 fork 出自己的版本進行開發,甚至最後發 pull request 要求 merge。
  5. 根據 fork 我就可以看到這個專案的分支 Network 狀態。有時候可能本來的程式不好用或爛掉了,你就可以查看看有沒有人寫做 patch 改進。
  6. 漂亮的 Source code browser,並可以針對 commit 來做留言討論,甚至標明是 source code 的哪一行(請把滑鼠移到原始碼的行數旁)。
  7. 提供 tarball 下載,即使沒裝 git command 也十分方便下載。
  8. GitHub 可以直接當做 Ruby gem server
  9. 針對 Repository 可以搜尋 code, commit message, author 等
  10. Git (我的感覺)比 SVN 又快又穩,用 SVN 常常會因為檔案太多中途失敗。

Github 根本就是 Open source developer 的 social networking 啊,聽說這股浪潮已經從 Ruby/Rails 圈吹到 JavaScript 跟 Perl 了(?),這都要歸功於 Git 這套優異的分散式版本控制系統。

BTW,幫忙宣傳 Jserv 在這週二的演講:我愛 Git – 有效使用分散式版本控制系統

Ruby & Rails on Rails 進階書單

都2008年了,還看我前年列的書單讓我有點不安,只好再整理一次。這次不列”所有”了,紅了之後入門書太多。而是整理我覺得值得一念的書及PDF。

Ruby

Ruby on Rails

投影片:Practical Rails2

釋出今天在OSDC的投影片,下載PDF請按此。題目雖然定成 Practical Rails2,但主要的內容是談 RESTful Rails 實做。

有了上禮拜在 HappyDesigner3 的經驗,這次試著講慢一點,應該有穩一點。
(開始前挺緊張的,結果人一半跑到隔壁聽 Keroro 桌面,瞬間壓力減輕不少 XD)
準備的投影片到上台前有了150張,本來還擔心會不夠,結果還講不完,只好跳掉了兩個自己寫的 Rails Plugin 介紹… :p

well, 請多指教 :>

補充: 傳到 sliceshare 後,發現旁邊的相關投影片有一份 RESTful best practices也值得一看 (如果你還有興趣的話…XD)。

小探 Rails ActiveSupport

Update(2008/4/9): 這篇 RAILS RUBYISMS ADVENT也可以一看。

ActiveSupport 是 Rails 的工具箱。最近在看 Advanced Rails, O’Reilly 一書,有幾樣東西值得記上一筆:

JSON

我們有 Object#to_json,物件如 array,hash 等都可以呼叫 to_json 轉 JSON 格式,非常方便與 JavaScript 做銜接。

Blank

所有的物件都加上了 blank? 這個函式,回傳 true 如果是 1. 空字串 2. 只含空白的字串 3. false 4. nil 5. empty array [] 6. empty hash {}。所以別再寫 ( s.nil? || s.empty? ) 啦。

Class Attribute Accessors

可用宣告的方式定義 Class Attribute,如

  class Foo
     cattr_accessor :bar
     self.bar = ""
  end

這樣會定義出來的 C.bar 即 @@bar

Class Inheritable Attributes

Class Attribute 是整個類別繼承體系共用,這在我們寫 ActiveRecord 相關 plugin 時非常不適用,因為所有的 model 都繼承自 ActiveRecord,但是各自又要有不同的 Class Attributes 值。最常見的使用狀況就是 plugin 了,model A 和 model B 都 include 某個 plugin,但是這個 plugin 的設定值要不一樣。拿大家都在用的 attactment_fu 舉例:

class UploadImage < ActiveRecord::Base
  has_attachment :content_type => :image, :storage => :file_system
end

翻出 has_attachment 的 source code 你就看到這招了:

def has_attachment(options = {})
      ......
     class_inheritable_accessor :attachment_options
     self.attachment_options = options    # 這裡的 self 指的是 UploadImage
      ......
end

除了 class_inheritable_accessor(syms) ,還有 class_inheritable_array(syms) 和class_inheritable_hash(*syms) 等。

Class Attribute Accessors 的原理可以請參考 class instance variables 這篇。

Date and Time conversions

不需要每次寫 Helper 用 strftime,我們可在 environment.rb 新增自訂的 format,例如

 ActiveSupport::CoreExtensions::Time::Conversions::DATE_FORMATS.merge!( :foo => '%m/%d %l:%M %p')

這樣就可以對 Time 物件呼叫 to_s(:foo),內建還有 :default, :short, :long, :db 等等。

alias_method_chain

在 Rails source code 十分常見:

  alias_method_chain :target, :feature

等同於

  alias_method :target_without_feature, :target
  alias_method :target, :target_with_feature

Delegation

將 methods 傳給另一個 object

  class Account < ActiveRecord::Base
      has_one :foo
      delegate :free?, :to => :foo
  end

這樣 account.free? 就會呼叫 account.foo.free? 考慮 foo 可能 nil,我們可以多一個檢查:

  delegate :free?, :to => "something.nil? ? false : something"

甚至兩層,假設 foo 有 bar:

  delegate :free?, :to => "foo.bar"

這樣 account.free? 就會呼叫 account.foo.bar.free?

#Object#returning

讓你執行一些操作然後傳回:

 returning(User.new) do |u|
   u.name = "Foo"
 end

#Object#with_options

最常用在 routes.rb,不過其實任意物件都可以用,他會將參數自動 merge 到 method call 的 hash 參數:

 map.with_options( :controller => "people" ) do |p|
   p.root :action => "index"
   p.about :action => "about"
 end