I am interested in how RVM and rbenv actually work.
Obviously they swap between different versions of Ruby and gemsets, but how is this achieved? I had assumed they were simply updating symlinks, but having delved into the code (and I must admit my knowledge of Bash is superficial) they appear to be doing more than this.
Short explanation: rbenv works by hooking into your environment’s
PATH. The concept is simple, but the devil is in the details; full scoop below.First, rbenv creates shims for all the commands (
ruby,irb,rake,gemand so on) across all your installed versions of Ruby, that is for all files in~/.rbenv/versions/*/bin. This process is called rehashing. Every time you install a new version of Ruby or install a gem that provides a command, runrbenv rehashto make sure any new commands are shimmed.These shims live in a single directory (
~/.rbenv/shimsby default). To use rbenv, you need only add the shims directory to the front of yourPATH:Then any time you run
rubyfrom the command line, or run a script whose shebang reads#!/usr/bin/env ruby, your operating system will find~/.rbenv/shims/rubyfirst and run it instead of any otherrubyexecutable you may have installed.Each shim is a tiny Bash script that in turn runs
rbenv exec. So with rbenv in your path,irbis equivalent torbenv exec irb, andruby -e "puts 42"is equivalent torbenv exec ruby -e "puts 42".The
rbenv execcommand figures out what version of Ruby you want to use, then runs the corresponding command for that version. Here’s how:RBENV_VERSIONenvironment variable is set, its value determines the version of Ruby to use..rbenv-versionfile, its contents are used to set theRBENV_VERSIONenvironment variable..rbenv-versionfile in the current directory, rbenv searches each parent directory for an.rbenv-versionfile until it hits the root of your filesystem. If one is found, its contents are used to set theRBENV_VERSIONenvironment variable.RBENV_VERSIONis still not set, rbenv tries to set it using the contents of the~/.rbenv/versionfile.(You can set a project-specific Ruby version with the
rbenv localcommand, which creates a.rbenv-versionfile in the current directory. Similarly, therbenv globalcommand modifies the~/.rbenv/versionfile.)Armed with an
RBENV_VERSIONenvironment variable, rbenv adds~/.rbenv/versions/$RBENV_VERSION/binto the front of yourPATH, then execs the command and arguments passed torbenv exec. Voila!For a thorough look at exactly what happens under the hood, try setting
RBENV_DEBUG=1and running a Ruby command. Every Bash command that rbenv runs will be written to your terminal.Now, rbenv is just concerned with switching versions, but a thriving ecosystem of plugins will help you do everything from installing Ruby to setting up your environment, managing "gemsets" and even automating
bundle exec.I am not quite sure what IRC support has to do with switching Ruby versions, and rbenv is designed to be simple and understandable enough not to require support. But should you ever need help, the issue tracker and Twitter are just a couple of clicks away.
Disclosure: I am the author of rbenv, ruby-build, and rbenv-vars.