更简单灵活地管理 Ruby 版本

839 查看

概述

这篇文章教你怎么用 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