如何處理不同版本的 Gem 執行檔,以 Rake 0.9.0 地雷為例
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