Update(2011/8/31): 正式釋出! Rails 3.1.0 has been released!
照慣例來整理一篇 Rails 3.1 重點,花了點時間看過一遍 Changelogs (TL;DR;)。
新的預設 jQuery
jQuery: New Default: 官方的說明
jQuery 取代 prototype.js 成為新的預設 JavaScript 函式庫。另外,RJS 也從核心中被移出成為 Plugin。還記得當年令人興奮的 RJS 功能,可以很方便的寫簡單的 Ajax 效果,如今又回到直接寫 JavaScript 才是王道。
Assets pipeline
RailsConf 2011, David Heinemeier Hansson: 今年 DHH 在 RailsConf 的演講,重點就在介紹 Assets pipeline。
靜態檔案成為一級公民了,Rails 3.1 透過 Sprockets 打包和壓縮靜態檔案,也支援編譯 Sass 和 CoffeeScript。細節請參考我書的 Assets 一章。
將 CoffeeScript 納入預設有不少爭議,畢竟用 CoffeeScript 實在又多了學習負擔,不是這麼多人喜歡。不過它其實只是 Gemfile 預設載入的一行而已,如果不用拿掉即可。
HTTP Streaming
HTTP Streaming 功能是 Rails 3.1 的一個實驗性突破,可以在 render 樣板的同時,就同時開始下載資料來節省時間。原理是 HTTP 1.1 協定中的 Chunked transfer encoding 傳輸機制。我推薦可以看看 Facebook 的 BigPipe 應用其實就是這個技術。
這功能預設是關閉的,而且也不是打開設定就馬上可以享受到。因為 render 的流程不同了,本來可以先 render template 再套 layout 的,用 streaming 的話是改從 Layout 先開始,由上往下一行一吐出結果就丟給瀏覽器,因此需要搭配注意的細節不少,像是要用 Ruby 1.9、網頁伺服器要支援、template 中不能讀取 layout 中的變數、使用 provide helper 取代 content_for、Controller 的操作必須盡可能的改成 Lazy method (也就是真正耗時的動作得實際發生在 View 中,例如 SQL query,不然時間卡在 Action 裡沒進到 View 就沒辦法提早傳結果出去啦。好加在 ActiveRecord 的 Query 都已經是 Lazy method 了),最後所有你用到的 Rack Middleware 層都必須支援 HTTP Streaming,萬一其中有 Middleware 需要等 response 完整的 body 內容才能處理,那麼就會卡住而失去 Streaming 提早送資料給瀏覽器的意義。
Migration
Reversible migration:新的 change 方法可以不需要分開寫 up 跟 down 了,Rails 會自動對應出 down 的操作,猜不出來的時候才會要你補寫 down 方法。
還有,Migrations 內統一改用 Instance methods 而不是 class methods 了,寫 def up 和 def down 即可,不需要 def self.up 和 def self.down。
Rack::Cache
加入了 Rack-cache middleware ,搭配 #expires_in, #fresh_when, #stale with :public => true 等方法,並使用你設定的 Caching store 來存放資料 (例如memcached)。
注意到因為有了 Rack::Cache,原本 Controller 的 Page caching 被移除不需要了。
採用 Rack-caching 真正的重點倒不是在於增加效能,而是在於它讓你無痛就開始寫符合 HTTP caching 標準協定的程式,讓你之後有流量需求時,可以很彈性地轉換到真正的 HTTP caching 伺服器上,例如 Varnish。詳情請參考Rack-cache FAQ。
Mountable Engines
Engine 被改的更為獨立,可以擁有獨立的 routes 和 namespace。請參考 API 文件,或是這篇簡介 Mountable engines in Rails 3.1 beta: getting started
ActiveRecord/ActiveModel 相關
採用 SQL Prepared statements 了,增加複雜 SQL query 的效能。
Mass assignment 可以設定 attr_proected 和 attr_accessible 因應不同角色而有不同限制,挺不錯實用的功能。詳見 API 文件。
Custom ActiveRecord Attribute Serialization: 支援不同的 Serialize 方式
ActiveRecord Identity Map:支援 Identity Map,相同的資料庫資料也一定會是同一個物件,可以節省資源增加一致性。不過因為行為有些改變,所以預設是關的,詳見
API 文件。
ActiveModel::SecurePassword,可以存密碼, 不過我覺得沒啥實用,大家都裝認證相關的 Gem 來用
新的 update_column 方法,這會完全忽略 validations 和 callbacks。本來的 update_attribute 雖然會忽略 validations,但是會跑 callbacks。
ActionPack 相關
ActionView 相關
-
form_for 的 :method 參數可以不必放 :html 裡面:也就是
form_for(@post, :html => { :method => :delete })
變成 form_for(@post, :method => :delete)
-
如果 form 裡面有用 file_field 檔案上傳,Rails 會自動幫 form_for 加上
:multipart => true
參數,這樣就不怕忘記啦,超棒。
- 新增 j() helper 是 escape_javascript() 的別名
- 新增 data 參數方便設定 HTML5 data-* 屬性:
tag("div", :data => {:name => 'Stephen', :city_state => %w(Chicago IL)})
會輸出 <div data-name="Stephen" data-city-state="["Chicago","IL"]" />
其他
- 在 rails console 中,改成預設會顯示 SQL query log。
- CSS Sprites: DHH 去年 RailsConf 講過要有,很抱歉這次 3.1 沒有喔!! 這張票還沒兌現。
Rails 3.2 ?
展望未來,我想 Rails 有兩大開發重點方向:
支援 Rich clients 的 API 介面
@DHH 的 37Signals 用了 backbone.js 來做 Basecamp mobile 版。而 @wycats (Rails3 架構師) 加入了 SproutCore 團隊,今年他在 RailsConf 的演講 Building Rails Apps for the Rich Client 就在研究他們如何在 Rails 上設計 API 搭配 SproutCore。
果然,這一篇 Rails core team 成員的
A New World of Resources 透漏了他們打算從乏人問津的 ActiveResource 下手。看來設計出一套給 Rich clients (例如 JavaScript MVC 框架) 的 API Convention 慣例,會是下一個大目標。
Middleware 大改造
看完 RailsConf 2011: Aaron Patterson 的演講,你會發現要做 HTTP streaming 真的很難,所有 Rack Middleware 都要重新看過,因此 @tenderlove 提出了新的 Rack 介面計畫想要改寫。另外就是他發現 Rails 2 到 Rails 3 的 RPS 效能變差的主因是太多 Middleware 造成 call stack 太深了。Rails 2.3 有 51 deep、Rails 3.0 有 60 deep,到了 3.1 達到 67 deep。這也是他想要改進的地方。增加效能、節省記憶體使用量是 Rails 3.2 的一大目標。