Getting Started With RVM: Features To Use and Pitfalls To Avoid

There is a lot of old, outdated, and just plain wrong information floating around about RVM (this is the internet after all), so after some requests from you guys, I bring you an overview of RVM: How to get started correctly, what you need to know, and how to use cron and sudo.

What is RVM?

RVM stands for the Ruby Version Manager. It is a piece of software that separates your entire Ruby environment in to component parts, separating your interpreter, installed RubyGems, and even docs. This lets you switch between different projects at will and use different versions of Ruby and different sets of gems at will.

Why use RVM?

In addition to managing Ruby versions (for which it gets its name), RVM also provides other features such as gemsets. This allows you not only to segregate Ruby versions, but also different versions of gems between two projects. The classic example of this sort of usage is where gems are not compatible as in Rails 2 and Rails 3.

Additionally RVM allows you to create a per project .rvmrc file. This lets you change the settings of RVM per single project and directory, preventing you from having to remember to manually set your Ruby version for each project that you’re working on.

So, how do I get it?

Now that you know what RVM can do, you can install RVM with a simple one liner: curl -L https://get.rvm.io | bash -s stable --ruby

This will get your Ruby 2.0, but if you prefer 1.9.3 or some other version you can specify that as well: curl -L https://get.rvm.io | bash -s stable --ruby=1.9.3

Don’t worry too much about what version you pick right now, that is one of the features of RVM, you can always add another version later.

Once everything is installed you’ll get a message from RVM saying something like:

* To start using RVM you need to run `source /Users/twood/.rvm/scripts/rvm`
in all your open shell windows, in rare cases you need to reopen all shell windows.`

This simply executes the .rvm/scripts/rvm file in the current shell, as in bash the source command is synonymous with ..

Now what?

Once that is complete you can check to see that RVM is installed with rvm info which will give you information about your current setup including binaries, environment variables, and system info. If you’d like you can also do rvm notes to view version notes.

Now is also a good time to check your current Ruby version as well with ruby —version which should match whatever you specified at install time. RVM refers to each version of ruby as Rubies. If you want to install other Rubies you can do so now with just a few steps. For example if you’d previously install 2.0 and would now like to use 1.9.3 you’d simply:

rvm install 1.9.3
rvm use 1.9.3
rvm rubygems latest

This would allow to have Ruby version 2.0 and 1.9.3 installed. To switch between the two, simply tell RVM which one you’d like to use: rvm 1.9.3 or rvm 2.0 which is short for rvm use 1.9.3 and rvm use 2.0 with the only difference being a confirmation message at the terminal.

Keep in mind that if there is not a binary version available the install time will be significantly longer as the Ruby version will now need to be built from source. To see what Rubies you have installed simply use: rvm list

This is all fine and good if you’re after a specific version, but RVM even provides a way to list off all the available Rubies: rvm list known (53 versions at the time of this writing).

Now that you have all the versions that you want installed, its time to pick a default, otherwise you’ll have to set your new version every terminal session, not productive. To check your default you can use rvm list again and you’ll see something like the following:

$ rvm list

rvm rubies

=* ruby-1.9.3-p429 [ x86_64 ]
ruby-2.0.0-p195 [ x86_64 ]
# => - current
# =* - current && default
#  * - default

Now to change your default all you need to do is use the —default switch as in rvm use —default 1.9.3. So fare we’ve only used the . version numbering convention, this tells RVM to look for and use the most up to date patch level for that version. For example if you wanted 1.9.3-p125, but only specify 1.9.3, you’re going to end up with ruby–1.9.3-p429 as that is the most current patch level listed in the $rvm_path/config/db file.

As mentioned above RVM provides the ability to create per project .rvmrc files that alter the gemset and Ruby version that RVM uses automatically. For example if you have a project in your ~/projects/my187project that you want RVM to use Ruby 1.8.7 for you can do:

cd ~/projects/my187project
rvm —rvmrc —create 1.8.7@my187project

There are many options you can set in your .rvmrc file, for the full list see the .rvmrc documentation.

RVM and Gemsets

Because RVM completely separates your Ruby setups in to independent entities your ruby executable, gems, and irb are self contained as well from each other and from the system and you can have separate named Gemsets.

For example you can have a testing gems set by using: $ rvm gemset create testing gemset created testing => /Users/twood/.rvm/gems/ruby–1.9.3-p429@testing

We can then go ahead and switch to this gem set using rvm 1.9.3@testing and install gems (e.g. gem install rails). Note that we don’t use sudo to install gems. This brings us to the next point:

RVM and sudo

By now you know that RVM creates separate gem directories for all of your Rubies and that you can have different named gemsets, but a consequence of this is that you DO NOT use sudo when working with RVM gems. This is because running sudo is the same as running another shell as the root user causing all the RVM setup (including environment variables) . As the RVM documentation puts it “You will start to think that someone has a voodoo doll of your application…”

RVM with Cron

When you schedule a job with Cron, at the specified time the system will launch a shell (usually /bin/sh) with a specified $PATH listed in /etc/crontab. As you may imagine this means that all of the setup that RVM has done is inaccessible to cron. If you really want to see this in action you can add the following job to cron: * * * * * env > /tmp/cron_env Once you see ’/tmp/cron_envget created, kill the job, and compare the file to you runningenv` yourself. Now you really see the issue. Fortunately thre is a way around this.

Use RVM wrappers

RVM provides a wrapper for every installed ruby and gemset that allows for usage with command-line tools such as gem, rake, and ruby. If you want to take a look at them, they live in $rvm_path/bin. We can take advantage of this fact and use these wrappers to craft cron jobs that will have the correct environment. So for example if we are using the ruby ruby–1.9.3-p429@my_project then we can create a cron job like the following:

1 15 * * * /usr/local/rvm/bin/ruby-1.9.3-p429@my_project /path/to/my/script.rb

Note that you can also load the environment from a separate shell script now that you know where it lives, but I personally prefer this option as it makes it clear whats going on when I edit my crontab.

Conclusion

We’ve now gone over the basics of how to use RVM to customize your Ruby environment. For beginner to intermediate day to day use you should be good to go from here, but there is a lot more to RVM than listed here. If you want to know more, just send me an email and I’ll do my best to answer your questions or address them in a future blog post. The RVM documentation is invaluable and can be found here.