RubyKaigi 是日本的 Ruby 年度大會。2009 年第一次去日本參加時,非常興奮能在 Ruby 發源地與全場四五百位 Rubyist 一起聽 Ruby 發明人 Matz 演講,現場歡聲雷動。當時就發願有機會也要上台分享。今年第二次投稿終於獲選了啦,我的題目是 BDD style Unit Testing,挑戰生平第一次英文演講。
<- Speaker 專用 Badge,爽!! It's awesome!
三天的議程在此,目前開放報名中。
😆 👨🏻💻 📚 🚀 💰 ✨
Update: Rake 0.9.1 回復了這個不相容變更,改成加上 Deprecation 警告:Global access to Rake DSL methods is deprecated. Please Include … Rake::DSL into classes and modules which use the Rake DSL methods.”。
前一陣子 Rake 0.9.0 發佈了,結果讓大家雞飛狗跳,因為他有個不向後相容的 API 更動。
## Version 0.9.0
* *Incompatible* *change*: Rake DSL commands ('task', 'file', etc.) are
no longer private methods in Object. If you need to call 'task :xzy' inside
your class, include Rake::DSL into the class. The DSL is still available at
the top level scope (via the top level object which extends Rake::DSL).
所以一旦你 gem install rake 升級到 0.9.0,那麼打 rake 就是用這個的版本,碰上你的專案不相容的話(例如 Rails 3.0.7 之前版本不相容),可以怎麼辦?
1. 移除 Rake 0.9.0 回到 0.8.7,但是常常會在不同環境下又不小心裝到,然後又爛掉了,是個不太可靠的方法 XD
2. 如果有用 Bundler 的話,你可以在 Gemfile 中指定 gem 'rake', '0.8.7'
,然後每次打 bundle exec rake
就是用 0.8.7 的版本了。BTW,如果指定了 0.8.7 還打 rake
的話,你會看到以下錯誤:
rake aborted!
You have already activated rake 0.9.0,
but your Gemfile requires rake 0.8.7.
Consider using bundle exec.
(See full trace by running task with --trace)
其實 Rails developer 應該都用 Bundler 了,而且也知道 bundler exec
的用途,但是直到這次事件前大家都沒習慣指定 rake 版本,因為 0.8.7 大家用了兩年都沒事啊,所以都習慣打 rake
而不是 bundle exec rake
。
2-1. Bundler 有個功能是 bundle install --binstubs
,這會建立一個 bin 目錄包含所有 Gemfile 裡面用的執行檔。所以改打 bin/rake
即可。
2-2. 承上,嫌 bin/rake
還是太麻煩? 如果你有用 RVM 的話,在專案目錄下放個 .rvmrc 加上 export PATH="./bin:$PATH"
,這樣又回到只要輸入 rake
即可。( .rvmrc 的主要用途是指定此專案使用的 Ruby 版本,例如 rvm ree
)
3. 試試 Rage,這是一個 script 檢查目錄下有沒有 Gemfile,有的話用 bundle exec rake
,沒有的話用 rake
。
3-1. 類似的方法還有 Automating bundle exec
Update(2011/8/31): 正式釋出! Rails 3.1.0 has been released!
照慣例來整理一篇 Rails 3.1 重點,花了點時間看過一遍 Changelogs (TL;DR;)。
jQuery: New Default: 官方的說明
jQuery 取代 prototype.js 成為新的預設 JavaScript 函式庫。另外,RJS 也從核心中被移出成為 Plugin。還記得當年令人興奮的 RJS 功能,可以很方便的寫簡單的 Ajax 效果,如今又回到直接寫 JavaScript 才是王道。
RailsConf 2011, David Heinemeier Hansson: 今年 DHH 在 RailsConf 的演講,重點就在介紹 Assets pipeline。
靜態檔案成為一級公民了,Rails 3.1 透過 Sprockets 打包和壓縮靜態檔案,也支援編譯 Sass 和 CoffeeScript。細節請參考我書的 Assets 一章。
將 CoffeeScript 納入預設有不少爭議,畢竟用 CoffeeScript 實在又多了學習負擔,不是這麼多人喜歡。不過它其實只是 Gemfile 預設載入的一行而已,如果不用拿掉即可。
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 提早送資料給瀏覽器的意義。
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 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。
Engine 被改的更為獨立,可以擁有獨立的 routes 和 namespace。請參考 API 文件,或是這篇簡介 Mountable engines in Rails 3.1 beta: getting started
form_for(@post, :html => { :method => :delete })
變成 form_for(@post, :method => :delete)
:multipart => true
參數,這樣就不怕忘記啦,超棒。
tag("div", :data => {:name => 'Stephen', :city_state => %w(Chicago IL)})
會輸出 <div data-name="Stephen" data-city-state="["Chicago","IL"]" />
展望未來,我想 Rails 有兩大開發重點方向:
@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 慣例,會是下一個大目標。
看完 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 的一大目標。
這次的 Ruby Tuesday 聚會開始報名了。 其中 Josh 是我的同事,去年的 RubyConf Taiwan 跟Ruby Tuesday 有講過一次,大家可能不陌生了。Zspencer 則是最近才新認識的朋友,他是放長假來台灣玩,專長是 JavaScript 和 Ruby,熱愛 TDD 測試和 Pair-programming。跟他第一次在 RGBA_ 聚會碰面的時候,他就教我 Game of Life 這個遊戲,然後兩個人 TDD+Pair-programming 用 Ruby 模擬這個遊戲。隨後換我教他玩 Ruby Warrior,他竟然堅持玩這遊戲也要寫測試,而且這幾天還錄了screencast XD 真是個對寫程式非常熱血的傢伙啊。anyway,當場就跟他邀約了一次演講,沒想到他這幾天連 outline 都準備好了。
時間: 2011/5/31(Tue.)PM7~PM9:30
地點: 台北市 theBase
報名網址: registrano.com/events/ruby-tuesday-19
這次試試看換新場地,感謝 evenwu 找到這家店。
首先,你一定會問幹嘛這樣做。我在上回的Git 演講中有提到:在 Git,你可以建立毫不相關的分支,用來保存其他資訊,就像目錄一樣。這 Branch 的用途不會被 Merge 進開發主幹,是完全獨立的。
實務上的一個應用,就是 Github 提供的 Github Pages 功能,只要你在專案下開一個 branch 叫做 gh-pages,那這個 branch 的內容就會變成靜態網頁。我之前的作法是先分支出來,然後再 commit 一次砍掉所有檔案。雖然結果是ok可以用啦,但是總覺得 gh-pages 這 branch 有 parent 就是意思不對勁,它是完全獨立於主幹的,不應該有 parent 資訊。
剛突然想到這個問題可以 google 看看(Github Pages上其實也有寫 XD),還真的有:
因為 git branch 預設是從 HEAD 分支,所以可以這樣 Hack HEAD:
echo ref: refs/heads/newbranch > .git/HEAD git rm -rf . # 砍掉所有檔案重來 ..... # 加新檔案 git add . git commit -m 'create new branch'
Git 1.7.2 之後版本有支援 –orphan 參數:
git checkout --orphan newbranch git rm -rf . # 砍掉所有檔案重來 ... # 加新檔案 git add . git commit -m 'create new branch'
git symbolic-ref HEAD refs/heads/newbranch rm .git/index git clean -fdx ... # 加新檔案 git add . git commit -m 'create new branch'
結果就像是這樣,master 跟 newbranch 的節點完全是分開的: