Get started right with RVM

Sep 2010 revised Nov 2012

I’ve always run Ruby with RVM. After @chopmo’s talk at Aarhusrb on RVM, I realized how much more I could get out of RVM. I found I basically use RVM as just a way to switch between Ruby versions and implementations, rather than leveraging the power of gemsets, installing gems on a user basis and the .rvmrc file. This post is a compiled version of what I learned from the previously mentioned talk and digging into the RVM documentation.

Installing RVM

If you haven’t already, install RVM at the user level:

$ bash < <( curl http://rvm.beginrescueend.com/releases/rvm-install-head )

With > 1 RVM users on the system, you may want to look into a system-wide system-wide installation. Otherwise, it is recommended to stay with the default user-wide installation.

To inject RVM into your environment .bashrc, .bash_profile, add the bit of bash it mentions at the end of the installation:

$ echo '[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm"' >> .bashrc

Fixing slow gem installations

Installing Ruby gems is by default a slow affair due to ri and rdoc documentation generation. Most likely you do not use this, and can disable it in return for vastly improved installation speeds:

gem: --no-ri --no-rdoc

Verify whether the rvm command works and check system specific notes:

$ rvm notes

Uninstalling all gems in system Ruby (Optional)

This step can safely be skipped, I simply performed it to clean my system.

With RVM installed, you can simply empty your current, global gemset (this’ll make more sense in a minute):

$ rvm gemset empty

You can easily take a backup of all your installed Gem’s and their versions with RVM:

$ rvm gemset export backup.gems

If you want to restore, it’s simply a matter of running:

$ rvm gemset import backup.gems

I’ll mention why rvm gemset {import,export} is as nifty as it is further down.

Installing Rubies

In RVM jargon Rubies are essentially Ruby versions, let’s go ahead and install Ruby MRI 1.9.3 (this is the default interpreter originally developed by Matz) first, and set that as our default interpreter. Afterwards, we’ll install Ruby 1.8.7, use RVM to easily switch between these two Rubies.

Installing 1.9.3 is the trivial matter of issuing:

$ rvm install 1.9.3

This can take a while, since it compiles from source. When this process has finished, switch to it with the following command to verify it works:

$ rvm 1.9.3 # shortcut for rvm use 1.9.3
$ ruby -v
ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-darwin11.4.0]

By default, your default interpreter is the system Ruby provided by your operating system, for instance in OS X this is MRI Ruby 1.8.7. You want to set this to a Ruby maintained by RVM to make use of all RVM’s features:

$ rvm --default 1.9.3

Restart your shell, and run ruby -v to verify it is not the default Ruby. Let’s install 1.8.7 along with 1.9.3:

$ rvm install 1.8.7

We can then switch to it just as before:

$ rvm 1.8.7

You are now up and running with two Rubies! With RVM, you can also install different interpreters such as Rubinius, JRuby or Maglev following the same installation procedure as above.

Gemsets

What?

The shortest explanation, is found within the name. Gem-sets.
RVM’s documentation puts it like this:

RVM gives you compartmentalized independent ruby setups. This means that ruby, gems and irb are all separate and self-contained from system and from each other. You may even have separate named gemsets. Let’s say, for example, that you are testing two versions of a gem with ruby 1.9.3-head. You can install one to the default 1.9.3-head and create a named gemset for the other version and switch between them easily.

Ideally you have a Gemset for each project that you are working on. This keeps your system clean, and eliminates “Gem clutter” and version mismatches. Also running bundle install will use the project defined gemset to also store the gems.

Contemporary note on gem versions and gemsets

When I wrote this article, bundler wasn’t commonly found in Ruby projects as it is now. bundler now solves the problems gemsets solved, by ensuring the correct versions of the gems for the specific projects are loaded into the environment by running scripts in your project with bundler exec rather than ruby. bundler projects thus make simpler approaches to the problem RVM solves possible, the most popular alternative nowadays is rbenv which I use on most of my systems these days.

Creating and using a gemset

Let’s go ahead and create a gemset:

$ rvm gemset create foo # Create gemset 'foo'
'foo' gemset created (/home/sirup/.rvm/gems/ruby-1.9.3-p0@foo).

$ rvm 1.9.3@foo # Switch to Ruby 1.9.3 with gemset 'foo'
$ gem list # Lists installed gems
*** LOCAL GEMS ***

We’ll go ahead and install a few gems in our new gemset, note that we are not using sudo to install gems, as the gemsets are stored in your user directory, and thus does not require administrator privileges:

$ gem install rails
$ gem list
gem list
*** LOCAL GEMS ***

abstract (1.0.0)
actionmailer (3.0.0)
actionpack (3.0.0)
activemodel (3.0.0)
[..]

Switching back to our default, global gemset, will reveal that rails and its associated gems above, was indeed installed in an isolated gemset.

$ rvm 1.9.3 # explicit: rvm 1.9.3@global
$ gem list

As expected, gem list returns an empty list since there are no gems in the global gemset which we cleared earlier.

Dumping and loading gemsets

Exporting a gemset is easy with RVM as previously mentioned:

$ rvm 1.9.3@foo
$ rvm gemset export rails.gems
$ cat rails.gems
abstract -v1.0.0
actionmailer -v3.0.0
actionpack -v3.0.0
activemodel -v3.0.0
[..]

You can then toss rails.gems to someone else, who’d be able to import that gemset as follows:

$ rvm use 1.9.3@rails --create # shortcut to create, then switch to it
$ rvm gemset import rails.gems

Installing all the gems from rails.gems with the right versions. This works great in teams, because of all the version conflicts that otherwise happen if you just install the newest versions of everything.

Contemporary note on exporting and importing gemsets

Nowadays we have bundler which also solves this problem, which used to be a massive pain. Nonetheless, it still has a wide array of usages today.

The global and default gemset

Two interesting gemsets are the global (~/.rvm/gemsets/global.gems) and default (~/.rvm/gemsets/default.gems) gemsets.

Gems in the global gemset, will be added to the global gemset in every new Ruby you install. rake, rdoc and bundler are good examples of handy global gems. The gems in the default gemset are the gems included in every newly created gemset.

rvmrc

There are three different kinds of rvmrc files:

  • System /etc/rvmrc
    • System wide configuration
  • User ~/.rvmrc
    • User wide configuration
  • Project .rvmrc
    • Project wide configuration

The most interesting one is the project .rvmrc. Every time you cd, RVM looks for a file called .rvmrc. If it finds it, it executes it. The following .rvmrc file would switch to Ruby MRI 1.8.7 and gemset project every time we change into that directory:

$ echo "rvm 1.8.7@project" > ~/projects/ruby-1.8.7-project/.rvmrc

I received a tip from RVM’s creator @wayneeseguin, that we can be even more sneaky about this:

$ rvm --create --rvmrc 1.8.7@project

This will create the gemset, and the .rvmrc file for the project all in one command!

To demonstrate what we just did:

~/projects $ ruby -v
ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-darwin11.4.0]
~/projects $ cd ruby-1.8.7-project/
~/projects/ruby-1.8.7-project $ ruby -v
ruby 1.8.7 (2012-02-08 patchlevel 358) [universal-darwin12.0]
~/projects/ruby-1.8.7-project $ rvm gemset name
project

My favorite configuration option is rvm_gemset_create_on_use_flag=1, having this line in /etc/rvmrc or ~/.rvmrc, gemsets will be automatically created if they do not exist when you switch to them:

$ rvm gemset list
gemsets for ruby-1.9.3-p194 (found in /home/sirup/.rvm/gems/ruby-1.9.3-p0)
gemsets for ruby-1.8.7-p358 (found in /home/sirup/.rvm/gems/ruby-1.9.3-p358)

foo
global
$ rvm gemset use foobar
Now using gemset 'foobar'

@wayneeseguin sent in another tip about how to add bash and zsh completion.

You can read more about rvmrc in RVM’s documentation.

Conclusion

This is all briefly describing what can be found in RVM’s (fantastic) documentation. For basic use, this article should cover the main topics, however, RVM can still do a whole lot more than I addressed here. The goal of this post was simply to get you started well, and right, with RVM.

Discuss this on Hacker News