更簡單靈活地管理 Ruby 版本

darkbaby123發表於2019-02-16

概述

這篇文章教你怎麼用 ruby-install 和 chruby 這兩個工具來管理和切換 Ruby 版本,相對 RVM 和 rbenv 來說這是一個更加輕量級且綠色環保的組合。

為什麼不用 RVM 或者 rbenv

首先說明一點,切換 ruby-install 和 chruby 並不是因為它們有什麼獨一無二的特性。它們能做到的事情 RVM 和 rbenv 都可以做到。如果你用著現有的工具感覺良好,也沒有嚐鮮的打算,完全可以不換。

那我為什麼要換?對我而言有幾個原因:

  1. 我想用一個 Homebrew 可以管理和升級的工具。

  2. 最好是工具不升級也可以安裝最新的 Ruby 版本。

  3. 功能和實現都很簡單。因為我只需要安裝和切換不同的 Ruby 版本,不需要其他的功能。

關於最後一點我想多說幾句,最近一年我對軟體的看法有些改變。對我而言好的軟體最重要的是 簡單夠用 。我不想為用不到的功能買單,它們可能增加潛在的複雜度和維護成本。我也不喜歡軟體為了達到功能做了太多 hack ,這會影響它跟其他軟體組合使用的輕鬆程度,進而影響未來替換它的輕鬆程度。我以前一直在用 RVM ,這次本來準備換成 rbenv ,但當我看了 rbenv 對 shim 的大堆解釋 後覺得這不是我想要的理想替代品。正好前幾天同事推薦 chruby ,@Hooopo這篇文章 也讓我覺得這應該是個不錯的玩意(希望沒拼錯那幾個 o),於是就果斷刪了 RVM 切換過去了。過程比我想得還要輕鬆許多。

使用 ruby-install & chruby

這其實是兩個工具,ruby-install 只負責下載、編譯和安裝多個 Ruby 版本,chruby 負責切換。它們的名字就是命令列的名字,所以你需要用到兩個命令(但都非常簡單)。你可以點它們的名字去 Github 看 README.md 。下面我只提供基本用法的例子(用的 Homebrew):

安裝 ruby-install

brew install ruby-install

安裝指定 Ruby 版本

ruby-install ruby 2.2.3

安裝 chruby

brew install chruby

切換 Ruby 版本

chruby ruby-2.2.3

然後在 .bashrc 或者 .bash_profile 里加入指令碼(具體路徑最好照官方說明來)。第一個指令碼載入 chruby ,第二個指令碼控制自動切換(按 .ruby-version 檔案)。

source /usr/local/opt/chruby/share/chruby/chruby.sh
source /usr/local/opt/chruby/share/chruby/auto.sh

關於預設 Ruby 版本,chruby 沒有這種命令,但我們需要的只是 “在適當的時候讓 chruby 自動切換到指定版本” 。chruby 會從當前目錄向上一層層地找 .ruby-version 檔案,所以你只要把預設 Ruby 版本寫在 ~/.ruby-version 裡就可以了,以此類推,如果需要在任何目錄下都能切換到預設版本,你可以考慮 /.ruby-version,我沒這個需求,就沒有嘗試。

在命令提示符裡顯示 Ruby 版本

這幾乎是 Ruby 開發的 “剛需” 了。我是自己寫了個簡單的指令碼做到這點的。原理很簡單,用 ruby --version 顯示當前使用的版本,擷取版本號再插入提示符就行了(修改 PS1 變數)。以我的 bash 舉例子:

# 如果當前目錄有 Gemfile 就顯示 Ruby 版本;如果有 package.json 就顯示 Node.js 版本,否則什麼都不顯示。
# 結果大概會顯示成 ruby@2.2.3 或者 node@5.0.0
function env_version {
  if [ -e ./Gemfile ]; then
    # ruby 2.2.2p95 (2015-04-13..) -> 2.2.2p95 -> 2.2.2
    echo "ruby@$(ruby --version | awk `{print $2}` | awk -F`p` `{print $1}`) ";
  elif [ -e ./package.json ]; then
    # v4.2.1 -> 4.2.1
    echo "node@$(node -v | awk -F`v` `{print $2}`) ";
  else
    echo "";
  fi
}

# 用 $() 嵌入 env_version 的結果
PS1="$(env_version)"

我自己用的 PS1 變數顯示了路徑,Ruby/Node.js 版本,和 Git 分支名。感興趣的可以參考 我的 dotfile,最終效果大概如此:

~/workspace/my-project ruby@2.2.2 [staging] $

最後附帶一點,如果不想頻繁地敲 bundle exec xxx ,可以看看文末連結的 Automating bundle exec 。這是一個簡單的 alias 指令碼。不過我在同事的 rbenv 環境上沒試成功,不確定是不是受 rbenv 的 shim 影響。如果是的話,這也側面證明了 less hack 的好處。

參考連結

Install Ruby The “Postmodern” Way
Programmer`s guide to choosing a Ruby version manager
Automating bundle exec

相關文章