分類
Rails Ruby

Rails3 實戰手冊

Update(2011/4): 預計延到 2011 年中出版。
Update(2014/1): 無限延期…

Rails3 實戰手冊,這是我最近一次上課的講義,也是預計年底出版的內容 (書名未定)。也因為會要出版的關係,這份手冊的內容是 Copyright 的,而不是我一般慣用的 CC 授權 (除了投影片仍用 CC 授權),所以請不要轉載內文,更何況我會一直修訂啊。

之前應 OSSF 工作坊開了 Ruby/Rails 課程好幾次,所以陸陸續續開始寫投影片跟教材,加上這禮拜趁去台北市教師研習中心開課又重新好好整理了一次。目前狀況前幾章的完成度較高,會繼續努力修改成完整一本書的樣子,預計年底明年由 PcUSER 電腦人出版。

希望這本書能讓想入門 Rails 的朋友,可以實際應用在工作上無礙。有任何意見(書名有建議嗎?),歡迎告訴我。

分類
Rails Ruby

Rails3 RC 發佈: 重點導覽

RailsConf 結束之後就嚷嚷要發佈的 Rails 3 Release Candidate 候選版本終於出了(好吧,是三個禮拜前的事情了,這篇拖稿了 XD),如果你還沒進場,又是一個好時機。從我上次(疑,竟然是半年前了!!)整理 Rails3 Beta 發佈: 重點導覽 以來,又有了一些不錯的文件,經過筆者過濾挑選,重新整理 Rails3 的八大重點:

1. Bundler
2. ActiveRecord 的新 Query API
3. ActiveRecord 的新 Validation API
4. Views: XSS, Block Helper, UJS
5. I18n
6. 新的 Routing API
7. 新的 ActionMailer
8. Metal

如果喜歡看 screencast,官方也錄了 rubyonrails.org/screencasts/rails3

安裝

升級到 ruby 1.8.7 或 1.9.2,以及 rubygems 要 1.3.6 以上


gem update --system
gem install rails --pre
gem install mysql2

開始改用 mysql2 gem 吧,這一套修正了 multithreaded 及 Ruby 1.9 的 Encoding 問題

升級

如果是升級,重點 Bundler 和 Views 部分必須先搞懂,不然完全動不了。其他 API 變更的部份(Routing, ActiveRecord, ActionMailer) 在 Rails 3.1 之前暫時是可以 works。當然有空還是趕快研究一下囉。以下是兩篇有關升級的新文章:

* Upgrading a Rails 2 App to Rails 3
* The Road to Rails 3: make your Rails 2.3 project more Rails 3 oriented

Rails 本身升級是沒有問題,怕的是周邊的 Plugin 沒能跟上。railsplugins.org 有整理一些,可以找找 github 上有沒有 branch,而 Rails3 透過 Bundle 安裝還蠻方便的。

1. Bundler

* Bundler: Rails3 用來管理 Gem dependencies 的神器

2. ActiveRecord Query Interface

Rails2 的 finders, named_scope, with_scope 等用法,在 Rails3 統一為一種 Relation 用法,可以更容易做 composable(chainable)、Decoupled from SQL 以及 Lazy Loading。另外如果是有傳參數的 scope,也偏好定義成 class method,而不是 scope + lambda 了。以下是一些不錯的文章:

* Active Record Query Interface 3.0 基本用法介紹
* ActiveRelation: ActiveRecord Gets a Facelift 基本用法介紹
* Active Record Queries in Rails 3 基本用法介紹
* Advanced Queries in Rails 3 進階用法介紹
* The Skinny on Scopes (Formerly named_scope) 進階用法介紹,跨 Model 的 Scope 太厲害了。
* New Active Record scoping syntax 如果你在 Rails2 有使用 with_scope 或 with_exclusive_scope( :find => x, :create => y ) 請讀這篇。新的 Rails3 建議你改用 scoping, unscoped, create_with 等新用法,因為舊的用法行為有差異。

3. ActiveRecord Validation

* AR Validation 提供了新的 API 只要一行就可以整合同一個屬性的多個驗證,可以減少行數。
* 可以客製 EachValidator 整合進上述的新 API 之中
* 可以客製 Validator 包裝一大堆 validations,例如 validates_with ReallyComplexValidator
* save(false) 終於拿掉了,要跳過驗證儲存請 save(:validate => false)

* Validations in Rails 3
* Improved validations in Rails 3
* validates :rails_3, :awesome => true
* Independent Model Validators

另外就是驗證錯誤的 API 也改了:

* Errors#on 跟 on_base 拿掉了,請改用 Errors#[]
* Errors#add_to_base(msg) 拿掉了,請改用 Errors#[:base] << msg * Views 裡面常用的 error_messages_for 跟 error_message_on Helper 被拿掉了,請自己寫過(你可以參考 scafffold 產生出來的程式)或裝回 legacy plugin

4. View

* Rails3 如何換使用 jQuery
* Unobtrusive JavaScript in Rails 3
* 所有有傳 code block 的 Helper 都改成 <%= 的形式,
請參考 Rails3 如何寫 Helper 可以傳 Block 參數 一文
* Rails3 處理 XSS: Rails 3 Security Strategy,HTML 預設都會逸出了,不要逸出請用 raw Helper 或字串的 html_safe! 方法。

5. I18n

* 詞彙檔中的變數替換由 {{}} 變成 %{} 了。這有點惱人,我還碰到 redmine 的問題(redmine 使用 Rails2,但是卻因為裝了 Rails3 所以 i18n 也升級到 0.4.1 版本就爆炸了)
* 提供更多 backends,例如 ActiveRecord
* 加速功能!! Run, I18n, run!

6. Routing

* Rails3 重點導覽:新的 Routes
* The Lowdown on Routes in Rails 3 很詳盡的用法介紹
* The Powerful New Rails Router 進階用法
* Rack in Rails 3 結合 Rack 端點的應用

7. ActionMailer

底層由 TMail 換 Mail gem,一整個砍掉重練 API 大改。原本動態的 Notifiter.deliver_welcome_email 寫法變成 Notifiter.welcome_email.deliver,其中的 Notifiter.welcome_email 是一個 Mail::Message 物件。

* A Whole New ActionMailer
* Action Mailer in Rails 3
* 一個範例
* Inline Attachments for ActionMailer

8. Metal

* Rails3: 新的 Metal 機制

分類
Database Rails

Enterprise Rails: 資料庫篇

稿子是 2009 年底寫的,本來想一口氣連 SOA 的部份一起整理 (對 SOA 有興趣的話,可以看我之前的投影片 91 頁 ~ 119 頁),不過一直拖到現在。雖然內容還是有點些雜亂,而且現在流行 NoSQL (?),不過還是就貼出來吧。

這本 2009 年底的書,趁著轉職的空檔終於一口氣讀完了。有些重要的背景知識,如果你一直追所謂的最新技術,反而是學不到。這本書其實講 Rails 不多,前一大半都是在講 RDBMS 關聯式資料庫,後半則是 SOA 架構。

像 RDBMS 裡面的 referential integrity、composite key、DB View、triggers、materialized View 這些東西,因為身為 MySQL 使用者很少用到、Rails 也沒有內建支援,實際寫 code 好像也都在 application layer 應用層處理掉了,所以到底要幹嘛用的呢? 他們被發明一定有原因吧? 是在什麼情境上使用呢?

第四章 Database As a Fortress

作者非常強調資料庫的重要,一家企業最重要的資產是資料,而不是員工 (資料不見就全完了,員工沒了再找就有了)。Framework 會變、程式會有 bug、可能也不會只有 Rails 會去存取 DB (所以只用 ActiveRecord Validation 並不可靠),總之只有你的 RDBMS 可以保障資料的正確性,data integrity 長存。

PostgreSQL 也比 MySQL 適合企業應用,因為很多 SQL 標準 MySQL 並不支援 (很多直到 5.0 後才支援)。PostgreSQL 會輸掉市佔率的原因是 1. MySQL 背後有一家商業公司支持 2. PostgreSQL 有很長一段時間不像 MySQL 有提供 Windows 安裝包 (話說這本書對 MySQL 其實還蠻揶揄的)。

作者也不建議使用 migration,因為它沒有支援所有的 DDL (Data Definition Language)。反正只有跑一次,不像 DML (Data Manipulation Language) 會一直用,用 ORM 比較方便。

作者持續強調 referential integrity 對企業層級的上線應用程式非常重要。會說不重要的,一定是該死的 MySQL 使用者(died-hand MySQL users),千萬別因為你的工具(i.e. MySQL, Rails)沒有這個功能,就說不重要。

隨著資料越來越多,你的老闆會想要知道一些數據分析報表,這裡作者點出一個重要的議題:你的報表會害了你的網站!! 你越常去產生你的報表,你的網站就會越來越慢。”Report are killing your site!!” 為什麼呢? 因為去 DB 撈大量的資料做報表,是非常龐大複雜的 SQL 操作,你的 DB 的效能會被拖慢,整個網站的效能就跟著 down 下來。該怎麼解呢? 撈 report 的 queries 不要對 production database 做就沒事了吧?

這裡作者又對 MySQL users 揶揄了:因為大多數的 MySQL users 第一個想到的方案就是使用 master/slave 來解決,也就是讓 query report 對 slave DB 做,但是即時如此不會影響到 production 運作,也沒辦法解決 query 查詢很慢的問題。

這裡觀念上要區分的是 OLTP (Online Transaction Processing) 和 OLAP (Online Analytical Processing 這兩種類型的 query,前者是一般的讀/寫/更新,這種是會讓使用者可以馬上等結果,大部分的前台網站就是屬於這種。後者則是一個 query 就須需要收集上百萬的資料去分析,例如:有多少客戶買了產品A,又買了產品 B,依照地點跟時間。

因為 OLTP 和 OLAP 是如此不同,沒道理 database 的設計也相同。OLAP 要快,就必須使用 denormalized 非正規化的方式來存放資料。但是將正規化資料和逆正規化資料混雜在同一個 DB,則非常容易造成資料的混亂不同步,寫出 buggy 有臭虫的程式。

要解決這個問題的領域是使用獨立的 data warehouse 存放 denormalized 的資料。(書就到此打住了,作者推薦了 The Data Warehouse Toolkit: The Complete Guide to dimensional Modeling by Ralph Kimball 一書)

第五章 Building a Solid Data Model

Data layer 層級的 constraint 才保證一定正確,因為應用層的 Model validation 可以跳過,放在 code 裡也容易被改掉。作者也示範了這兩者都可以寫單元測試。

referial constraint 如果只用 Model 做,destroy 時就會失效。而 Model 要做 referial constraint 只能用 has_many :depentent 但是如果誤用了 :delete 就 orz 了。因此最保證的作法還是 data layer 做。

資料庫記得加 index 在 1. foreign key 2. 任何有 SQL where 條件的地方

第六章 Refactoring to Third Normal Form

3NF (三階正規化) 能做到 DB 資料不重複:只要不是 primary key、不是 foreign key、不是 intrinsic data(eg. name)、不是 measured value (例如 time, temperature),而是一個 literally bound data,都應該正規化出來新建一個 table。不先做,後來要加會十分痛苦,尤其在一個已經有資料的 production db 上。

範例中的有很多 table 都有相同的地址欄位定義:Postgres 支援 multipie inheritance,可以處理重複的 DDL,再搭配上 Rails 可用 plugin mixin 處理重複的 code。

這裡留下一個第八章才回答的問題,只有一個 primary key 沒辦法一次撈出 has_many 的 has_many 資料。多保留一個 foreign key 又可能造成 direct 和 in-direct 的資料不一定一致。

第七章 Domain Data

Domain data (指網站預先就有的必要初始資料,又叫做 seed data) 也應該使用 table 存,因為 1. 保持 referential integrity 2. 維護 3ND 跟擴充彈性。實作上則可以做成常數形式。

strategy patterns with domain tables 這招示範了將 Order PAYMENT_TYPE 變成 domain tables 來做,除了變成 constant object,情境是如果不同 payment_type 會有不同的 validation。首先變成 constant 後,可以順利將 validation code 都從 order 搬走。而再進一步 rails single table inheritance 和 template method 將 validation 分散到個別的 domain model。總之,作者將 domain data 的彈性做了非常好的示範。

雖然正規化會導致大量的 table 和 model,但是也因為如此每個都很小非常容易測試,bugs 也就容易集中在小區域容易找到。

第八章 Composite Keys and Domain Key/Normal Form

這章討論 composite key 的優缺,以及如何使用。

ID column 系統的優點 1. Rails 內建 2. 簡單,除了 primary key 之外皆可修改,物件的 primary key 一定不變 3. 提供與真實資料的間接性,因此也不需有修改 primary key 的機會。 4. unique key 好做

composite key 的優點就沒這麼顯而易見,也不一定用的到。他的用途在於提供一種特別的 data integrity。table 中不一定可以發現有 natural composite key, 但是如果有而你忽略他,可能會有大問題。這個情境就是:

只有一個 primary key 沒辦法一次撈出 has_many 的 has_many 資料,如果只是加上一個 reference key, 可能導致 refential integrity hole. 這時 composite key 才是唯一解決之道。

DFNF 比 3NF 更近一步保證 referential integrity 在複雜的 relationship 中。不能因為工具沒有,就覺得不重要。因為 Rails 沒有內建,導致很多人不知道 DK/NF or natural keys 等這些已經發展成熟的資料庫基礎理論,在設計 schema design 上而有很大的缺陷。

先來檢討 single column ID 是否應該用 Rails 內建的數字,首先找有沒有別的 unique column,再來覺得它是否不會 或 不常變更,特別是連編輯介面都沒有的 domain data 特別符合這個條件,如果是,則可以用 set_primary_key 換掉,移除不必要重複 id column。不過,如果不是 domain data, 我們就必須產生這個 primary key,用法是寫在 before_create 裡,另外要注意還是使用 self.id。一個額外的好處是,這些可能被當做 foreign_key 的 nature key,也是有用的資訊,不像本來的數字 id 一定還要去本來的 table 查。

這裡我有個疑問是 Is there a REAL performance difference between INT and VARCHAR primary keys? ,在我碰到的例子是,很多人擔心非 integer 當 key 會影響效能 :/ (題外話,很多人愛用 type code,但都被我建議改成 string constant ) 但是我想這差距的微乎其微,尤其在你沒有上百萬的資料列。重點還是,你選的 nature key 不需要有被修改的可能 :>

Rails 要支援 composite keys 有兩個方法,一個是使用 Dr. Nic Williams 的 plugin,一個是本書作者的 Rails-DK/NF hybrid 法:

具體的作法是,保留 ID column 欄位,但是 DB 還是加上 composite key 的 foreign key referential integrity 限制。好處在 Rails 裡面不方便改 primary key, 當有修改的需求時,使用 hybird 法就不錯簡單(不需要裝plugin)。但是回過頭想,如果你需要修改 nature key,可以先想想是不是最好的作法應該是刪掉舊的,插入新的。

一個小技巧是附寫掉本來的 writor,這樣就不需要手動設定 composite key 的值了。如果要改已經被 reference constraint 限制的 composite keys 怎麼辦? 直接改會爆,這時候需要使用 deferrable constraints 的機制和 transaction。

不過 hybrid 法的缺點是 1. 因為維護兩套 index key 的關係, 新增修改刪除的 index cost 比較高。 2. 需要多寫上述的 code 才能省掉手動設計的麻煩。

書沒寫哪個最好,看起來是如果非得有修改 nature key 的需求才只用 hybrid 法。

第九章 Guaranteeing Complex Relationships with Triggers

stored procedure 和 triggers
使用 PL/pgSQL 做例子。

第十章 Multiple Table Inheritance

Rails 的 polymorphic associations 功能讓你可以定義兩個 table 的關係,不需要事前知道是哪一個 table。

不過,polymorphic associations 違反了 referential integrity !! 原因很簡單,既然不知道 _id 會指到哪個 table,自然也就沒辦法在 DB layer 加上 foreign key constraint

什麼是多型?

要達成多型的方式,實作上要考慮的是 STI 或 MTI:前者 Rails 有內建,後者 Rails 有用了 polymorphic 方式來達成 XOR relationships,也算是一種簡易的 MTI。

這本書用了 logical 和 physical models 來分別描述概念上和實際上的切法

STI 適用於 subclass 共用很多 data。如果共用的不多,除了浪費 table, model 也會被 getter 和 setter 污染。另外因為 class name 寫在 table 了,如果要修改 class name 會很麻煩。

這裡提的 MTI 作法是,還是為了要用到的 foreign key 開欄位,並且也為每個關係加上 belongs_to,但是允許 null 值,因為要做 XOR on columns: 要用 boolean 做 XOR,兩個還好做,超過三個就複雜了。這裡的作法很聰明,轉成數字再相加,只要檢查是不是等於 1,用這樣的方法做 database constrant check。

都加了 belongs_to,要怎麼做到多型。這裡作者使用了 reflection 和 inheritance relationship 的技巧,在 parent object 上實作了 getter 和 setter method,厲害。我們也可以實作一個 Factory method 在 parent 上,來建構適合的 sub-class。

第11章 View-Backed Models

有些複雜的 join 和 conditions 單靠 active record 寫不出來(畢竟簡單好用的東西,畢竟是犧牲一些不常使用的功能),而必須寫一些很醜的 SQL 混雜 active record,但是這樣就失去使用 active record 的意義(與DB-independent)。如果要漂亮,只能先盡可能先撈出來,然後再從 application layer 層過濾資料,但是這樣又失去效能,畢竟撈資料是 DB 的專長。

解法是 view-backed model,materialized view。

database view 有兩個定義 1. named subquery 2. a table that is defined by an algorithm
後者的實作是,我們先用 SQL 定義 DB view,然後就可以用 ActiveRecord 代表那個 view/table,更 cool 的是,還可以加上 association!! 當然,這是 read-only 的,記得不要加 destroy。

subquery 的定義也表示,你不能對 view/ view-backed models 操作 insert/update/delete/reference/constraint/index。
references 也不需要,如果你要 reference,就表示你應該加到 view 裡,constraint 也是。

indexing 也無,畢竟是 just-in-time 撈出來的資料。但是本來的 index 欄位當然還是有作用。別氣餒,畢竟本來使用 View 的目的不是效能,而是為了讓 AR 更簡潔清楚。如果真的需要效能,下一章的 materialized view。

第12章 Materialized Views

materialized view 就是 cached 的 view。既然是 cache,就一樣有 cache 的議題: 資料的更新,何時由誰 expire?

materialized view 是 cache-complete copy of view, 也是全部都有留資料,不像 memcached 會把不常用或超過記憶體的資料移除。

幾個重點: 1. materialized view 既然是實體的 table,也就可以加 index 2. 要加上 refresh function 當偵測到 base table 有修改 3. 或是 invalidation function 如果不想馬上更新 4. 在 base table 加上 triggers 以偵測修改 5. auxiliart view, reconciler view 隱藏實作細節

不過看完還是覺得使用 materialized view 真是挺難的!! XD

分類
Rails

Rails3: 新的 Metal 機制

新的 Rails3 Controller 重構後,變成 ActionController::Base < ActionController::Metal < AbstractController 的繼承體系。除了 ActionMailer 繼承自 AbstractController,讓 API 與 Controller 一致之外,新的 ActionController::Metal 更是充滿玩味。

故事可以從上個禮拜,Yehuda 把 Rails 2 的 Metal 移除了(commit),根據 commit 的說明,Rails 2 的 Metal 在 Rails 3 裡面,可以用 1. 放在 Route 之前的 Rack middleware 或 2. 放在 Route 之後的一個 Rack endpoint,而這個 Rack endpoint,除了自己實作 Rack app,我們也可以用 ActionController::Metal 來實作出自己的客製化 Controller。

Rails2 發明 Metal 原因是,有些事情不需要完整的 Controller 功能,希望能夠越快越好,例如 XML/JSON API 等。而 Rails2 的 Metal 雖然非常快,但是沒什麼彈性,完全不能使用 Controller 的功能,例如用 Layout, Template, Sessions 等,基本上就跟單純的 Rack middleware 沒什麼兩樣。但是在 Rails3 中,可以透過自繼承 ActionController::Metal 做出白紙般的客製 Controller,可以有非常快的速度,如果有需要用到 Controller 的功能,也可以任意選擇組合加入,十分彈性。

例如,我們來實作一個超級精簡的 Static Controller:


# lib/static_controller.rb
class StaticController < ActionController::Metal
  include ActionController::Rendering
    
  append_view_path "#{Rails.root}/app/views"
    
  def about
    render "about"
  end
end
    
# config/route.rb
match '/about', :to => "static#about", :as => :about

這個範例有接近於 Metal 的速度,並加入了 Controller 的 Template 功能 (你可以參考 ActionController::Base 這是擁有全部功能的版本)。其中 “static#about” 是 StaticController 的 about action 縮寫,而在 Rails3 中,controller action 也都是一個 Rack app。

除了我的這個簡單範例,在 The Powerful New Rails RouterUpgrading a Rails 2 App to Rails 3 的影片中,也有分別舉例。

總而言之,如果你在 Rails3 中不需要全部的 Controller 的功能,想要盡量拉高效能,有幾種推薦作法:

* 寫成 Rack Middleware,然後在 config/application.rb 中插入 config.middleware.use YourMiddleWare
* 寫成 Rack App,在 config.route.rb 中將某個對應的網址指到這個 Rack App
* 繼承自 ActionController::Metal 實作一個 Controller,其中的 action 也是一個 Rack App

其中的差異就在於後兩者會在 Rails Route 之後(好處是統一由 route.rb 管理 URL 路徑),如果繼承自 ActionController::Metal 可以有彈性獲得更多 Controller 功能。原則上,我想我會推薦 ActionController::Metal,寫起來最為簡單,一致性跟維護性較高。

另外,還有個小玩意, ActionController::Middleware 是 Controller 層級的 Rack Middleware,讓你可以在放入到某個特定 Controller 之中(也就是只有該 Controller 使用這個 Middleware)。不過呢,這個功能我到現在還沒看到任何實用的例子就是了。

最後,Yehuda 提供了一個 參考數據


fast: through middleware inserted at 0
slwr: through middleware inserted via @use@
rotr: through endpoint sent via the router
bare: through ActionController::Metal with self.response_body
cntr: through ActionController::Base with self.response_body
text: through ActionController::Base with render :text
tmpl: through ActionController::Base with simple render :template
layt: through ActionController::Base with render :template with layout

         real     rps
fast   0.004271   2900 Rack 極限
slwr   0.067029   2200 使用 config.middleware.use YourMiddleware
rotr   0.088085   2000 經過 Rails Route 之後
bare   0.103868   1900 使用 ActionController::Metal 的最快速度
cntr   0.355898   1070 使用 ActionController::Base 的最快速度
text   0.557127    825 使用 ActionController::Base 加上 render :text
tmpl   0.639581    765 使用 ActionController::Base 加上 render :template
layt   1.678789    375 使用 ActionController::Base 加上 Template 跟 Layout

分類
Rails Ruby

Bundler: Rails3 用來管理 Gem dependencies 的神器

Update(2011): Bundler Pro Tips
Update(2010/7/27): Bundle 1.0.0 之後不需要 bundle lock 了,只要 bundle install 就會自動 lock。預設都裝到 system gem 的位置。

Bundler 是一套為了 Rails3 所打造的全新 Gem dependencies 管理工具:一套基於 Rubygems 的更高階套件管理工具,適合讓 Application 管理多套 Gems 依存關係的複雜情境。而你在 Rails3 中 (Bundler 不只用在 Rails3,其他例如 Sinatra 或是 Rails2 也都可以使用) 要使用的 Gems,也都必須宣告在它的 Gemfile 裡,沒寫在裡面的話,就算手動 require 也找不到。這跟已往你可以直接 require 任意 rubygems 不同,在使用 Bundler 的環境中,要 require 什麼 rubygems 必須透過 Gemfile 管理。

Gemfile 的寫法大致如下:


  # 第二個參數可以指定版本
  gem "rails", "3.0.0.beta3" 
  
  # 如果 require 的檔名不同,可以加上 :require
  gem "sqlite3-ruby", :require => "sqlite3"
  
  # 可以用 Git 當做來源,甚至可以指定 branch, tag 或 ref。
  gem 'authlogic', :git => 'git://github.com/odorcicd/authlogic.git', 
                            :branch => 'rails3'
  
  # 可以直接用電腦裡的其他目錄
  gem "rails", :path => '/Users/ihower/github/rails'
  
  
  # Group 功能可以讓特定環境才會載入
  group :test do
    gem "rspec-rails", ">= 2.0.0.beta.8"
    gem "webrat"
  end


設定好 Gemfile 之後,我們有一些指令可以用:

  • bundle check 可以檢查目前缺少哪些 rubygem,然後你可以手動透過 sudo gem install 安裝到系統裡。
  • bundle install 安裝所有需要的套件。如果系統已經有裝了,就用系統的,不然會裝到 $BUNDLE_PATH 下,預設是你家目錄 ~/.bundle (因此請不要用 sudo 執行 bundle install)。如果來源是 git (例如上述的 authlogic),每次執行 bundle install 就會自動 git pull 更新,十分方便。
  • bundle lock 和 bundle unlock 會做 snapshotting 記錄下目前所有套件的版本在 Gemfile.lock,建議這個檔案也一起 commit 出去。適合要佈署或多人開發時,可以確保大家的版本都一致。不用手動lock了,bundle install 時就會產生 Gemfile.lock
  • bundle package 如果你的 Server 沒聯外網路,或是怕 rubygems.org 連不上,可以用這個指令把所有套件都打包到 vendor/cache 下。基本上,跟以往 Rails 1.X 2.X 時代佈署時會建議你盡量打包依存套件並 commit 出去,在使用 Bundler 後已經大大地不需要了,因為透過 bundle lock 我們就可以確保每台機器上執行的套件版本一致。
  • bundle exec 因為 Bundle 可以說是獨立出一個套件環境,所以如果有非 Rails 的指令需要執行,而且你的系統 Gems 又沒有安裝,那就會需要透過 bundle exec XXX 來執行。例如 bundle exec cucumber。
  • bundle show gem_name 可以查看這個 gem 的目錄位置
  • bundle open gem_name 可以用編輯器打開這個 gem 的目錄

開發 Rails3 實際用一陣子之後,發現很偏好將套件裝成 Gem 了(如果有提供 Gem 版的話),之前 Rails 1.X 2.X 時代會比較喜歡裝成 Plugin,因為想說別人要裝 Gem 可能會有問題,以及佈署也怕出包。但是有了 Bundler 之後,只要 Bundle install 就可以裝好並確保大家的版本一致會動。不像已往的 rake gems:install 超不可靠。可以透過 Bundle 裝這些依存套件也減少了需要 commit 出去的 vendor/plugin 檔案,讓你的專案 repository 變乾淨了。另外,我也超喜歡的 Bundler 可以支援 Git 來源,只要 bundle install 就會更新,不需要額外的管理工具去煩惱更新 plugins。

其他推薦閱讀:

分類
Rails Ruby

校園自由軟體工作坊 – Meet Ruby on Rails

Update: 投影片下載:遇見 Ruby on Rails

遇見 Ruby on Rails from Wen-Tien Chang

這週三 (2010/5/5) 晚上我在台大有一場 “Meet Ruby on Rails” 的演講,是由 OSSF 和台大資工系學會所合辦的工作坊。

不同於上次在清大的校園課程,這次只有安排 talk,沒有安排電腦教室給學員實作。給大學生講這個題目,我目前想要多準備一點軟性題目,少談一點程式碼。像是介紹 Web 軟體開發產業、為什麼採用 Web framework、為什麼用 Rails? 為什麼用 scripting 動態語言? 為什麼用 Ruby? 以及除了學校課程以外,我認為作為一個 Web-based 軟體設計師,可以學習的方向。當然,還有 Rails 的 live demo。

某方面來說,雖然題目是遇見 Ruby on Rails,但是我希望也可以讓聽眾遇見 Web application 軟體開發的樂趣。台灣的資工系學生畢業之後,大部分都投入硬體相關產業吧 (不同於美國的軟體業產值超過硬體,台灣的軟體業產值只有硬體的九分之一,真是九牛一毛啊 :~ )。如果這場演講可以讓他們多了解 Web 軟體產業,無論是不是喜歡 Ruby 或 Rails (就算是喜歡上 Python, Perl 也不錯),那就達到我演講的目的了。