If you are an active Ruby developer you probably know about and use RVM. For the past few years, many of us have turned to RVM to manage the various Ruby installations on our systems and the gemset feature to handle the gaggle of gems for various projects.
There are handy instructions on exactly how to install rbenv in the Readme on Github. If you’re using Mac OS X, I recommend going with the Homebrew install method; otherwise, the git/source method is simple enough.
One of more useful features of rbenv is the ability to specify a specific Ruby to be used within a certain scope. rbenv defines three levels of scope: global, local, and shell.
The global Ruby applies to all shells by default. local Rubies are set via a file,
.rbenv-version; rbenv recursively activates the local Ruby until in encounters another
.rbenv-version file in the directory tree. shell is applied across an entire shell session.
rbenv determines the which ruby will be used with a simple precedence model:
global → local → shell
In other words, the current shell ruby will override any locally defined ruby, which in turn overrides the global ruby.
The global scope is set like this:
To set the local Ruby:
$ rbenv global 1.8.7-p352
And to set a shell Ruby:
$ rbenv local 1.9.2-p290
$ rbenv shell 1.9.2-p290
--unsetoption will unset the Ruby currently assigned to a scope, letting the Ruby from the lower precedence scope show through.
And if you ever need to get back to the default Ruby installed on your system, such as that one that comes with Mac OS X, you can use the special
system keyword. For example, to make the default Ruby your global default:
If you aren’t sure what Ruby is currently active, or how it’s set, rbenv makes it very easier to find out. For example,
$ rbenv global system
$ rbenv versions * 1.8.7-p352 (set by /Users/stonehippo/.rbenv/version) 1.9.2-p290 ree-1.8.7-2011.03This indicates that the current Ruby is MRI 1.8.7 and that it has been set by the global rbenv version file. You can also see that MRI 1.9.2 and Ruby Enterprise Edition are also installed.
Although rbenv doesn’t install Ruby by default, there’s a handy plugin, ruby-build, that adds the ability to do that. Once installed, ruby-build makes it easy to install one or more the flavors of Ruby. For example, to get the latest version of MRI 1.9.2, you can do
Or how about Rubinius?
$ rbenv install 1.9.2-p290
ruby-build includes several built-in install definitions, and it’s trivial to create your own.
$ rbenv install rbx-1.2.4
In general, it’s far easier to use ruby-build and let it handle your installs, but you can also build your own Rubies. But really, why?
Managing Gems With rbenv
You can’t. And that’s a good thing.
First, rbenv automatically segregates any globally installed gems for each installed Ruby. So if you install Rails under MRI 1.8.7, it won’t be available to your MRI 1.9.2.
Beyond that, the recommendation is to use Bundler to handle gem dependencies. Follow this recommendation: it’s much saner than using RVM gemsets and easier to manage in the long term.
One Quirk: Rehash
There is one quirk of rbenv that might trip you up: the way it handles binaries installed by your Rubies and gems. All rbenv Rubies typically live in
~/.rbenv/versions, along with any gems you install. In addition, the binaries installed with some gems (such as
rake) also get installed in there. rbenv uses shim scripts, installed in
~./rbenv/shims, to handle pointing to the correct version of a given command when you swap Rubies.
The shims are a great thing. They guarantee that when you do something like this
the correct version (the one associated with the current in-scope Ruby) gets invoked. And even better, if the binary you want isn’t installed with the current Ruby, the shim will warn you:
$ rails new example-app
$rails new example-app rbenv: rails: command not found The `rails' command exists in these Ruby versions: 1.8.7-p352Great, right? So what’s the problem?
Well, whenever you install a new Ruby or gem, you need to let rbenv know that it needs to hook up the shims to any installed binaries. Fortunately, this is not that hard. You just need to use
rbenv rehash. For example, let’s say I want to install one of my favorite tools, Request Log Analyzer. Because RLA installs a binary command, I’ll need to
rehash to make sure it’ll work correctly.
$ gem install request-log-analyzer Successfully installed request-log-analyzer-1.11.1 1 gem installed $ rbenv rehashNot so bad, right? But don’t forget to do it. And this is another reason to use ruby-build to install your Rubies: it invokes
And A Caveat…
If you’re planning to use rbenv, remove RVM. They don’t play nice together. Things will appear to work, but they really won’t.