Choosing between Ruby environment managers: rbenv vs. RVM
Using a system’s default Ruby interpreter to develop projects and install required gemsets is a sure path to dependency nightmare. Each project needs its own environment independent from others. At the same time, the system’s installation of Ruby should be left intact.
This article gives a quick overview of the popular Ruby environment managers and provides a concise installation instruction for a painless setup on MacOS X.
To quickly jump to the environment manager installation click here.
Overview
There are two main options for environment management when it comes to Ruby. First one is the RVM
. RVM was the first decent environment manager which could manage multiple interpreters and per-project based gemsets, it is still very popular among Ruby developers. Although, not only the installation process of it is somewhat unusual for these days, but is also messes up with a lot of things in the system in a magic and incomprehensible way. For instance, RVM
ensures that a correct version of Ruby will be utilized in a project by replacing original cd
command in *nix
systems, which is way too much for nothing else but Ruby environment manager.
The other known option is called rbenv
. It’s a much more simpler and reliable solution, and it does not mess the system up, keeping everything local and manageable.
RVM and its downsides
So, what’s wrong with the RVM
? The installation of RVM
is quite bizarre for anyone without a background in Linux systems administration, and project’s homepage leaves even more for a reader to guess regarding RVM’s internal logic and implementation. RVM
gives an impression of the tool that mingles with the system in an irreversible way. Obviously, it’s a tested, trusted, and community verified tool that does not perform any malicious actions with your system, but the first impression it gives doesn’t look like something you would expect from a user friendly environment manager.
The installation requires you to add a pair of public GPG keys of project’s maintainers to your GPG keychain and then download and run a 1000 lines long bash script that will do the installation for you.
First, adding GPG keys:
Next thing that RMV’s website will suggest is to run the following command to continue installation:
This line downloads and runs RVM’s bash installation script.
Before running any unknown script I usually stop and suspend the installation process. You never know what that script is going to do to your system unless your read through it. RVM skips the “read” part right away. I’d call such installation process a bad practice. How difficult will it be to remove RVM from the system and clean up the traces? Was it to hard for creators to enable a Homebrew based installation? You can’t tell until you spend a considerable amount of time searching for the answers. And, again, doing a deep research of what’s supposed to be a simple Ruby environment manager is not something you would expect from a user friendly tool.
Interestingly enough, if prior to going all in and running an unknown script you think ahead and decide to check the official website for the uninstalling instructions, you won’t find them. There is a single mention of implode
command on the RVM’s CLI usage page. But according to that page:
implode - removes all ruby installations it manages, everything in ~/.rvm
implode
does not uninstall the RVM itself. Basically, there is no way to automatically uninstall RVM
other than manually cleaning up everything that the installation did to your system. And that’s a huge downside.
The only way to uninstall
RVM
is to manually clean up everything it did to your system.
If you proceed with the installation and run the second step from RVM’s homepage, the bash script will be downloaded and executed.
If you are as impatient as me, you would most likely hope that at least the usage of RVM is clear and simple after all that unknown compilation-installation-mess. I would argue that it’s not. Let’s think about a first time Ruby user who managed to install RVM
. After spending around 10 minutes reading, trying to understand, and installing RVM
the user will search the homepage for the link that describes some usage examples or the basics:
Did you find a page that explains the usage? Or maybe, CLI usage would be a better page to look at for the first time user? You would certainly hope that at least the basics are short and concise, because an environment manager is not the final goal of the whole process. The final goal is to develop using Ruby in a clean and isolated fashion.
The usage instruction of RVM is muddy and unclear. The understanding of correct way to use the tool might require even more time than its installation. So, if you have installed RVM by mistake, here is the way to clean everything up and uninstall RVM
completely.
Cleaning up after RVM
RVM can be uninstalled in a several steps. Here are two topics on StackOverflow covering the uninstallation of RVM
: How can I remove RVM (Ruby Version Manager) from my system? and Howto Uninstall RVM [duplicate].
0. Delete RVM installed rubies
If you have already installed and integrated RVM
into your shell, you will need to start with the rvm implode
command.
1. Removing the ~/.rvm directory
Some size stats before removing the directory
The pure default installation of RVM
on MacOS takes 181 Mb.
Remove RVM’s directory
2. Cleaning shell configuration files
Check the following files for the references to RVM and remove the RVM line from each of them:
~/.bashrc
~/.bash_profile
~/.profile
~/.zshrc
~/.zlogin
References look like this:
We can do a quick grep
to check if RVM
put itself there.
3. Removing unnecessary GPG keys
To remove public GPG keys of RVM maintainers we will need their user names. We can find them in the full list of public keys stored in GPG.
You can use any representation of user name in any uid
row listed in a key to delete it. I will use email address.
rbenv
rbenv
is short for Ruby Environment
. It’s a different command line tool that enables you to quickly and easily switch between different rubies installed on your system.
What I like about rbenv
is it’s simplicity and obviousness. It might look especially familiar for those coming from Python background, because rbenv, in fact, looks a lot like pyenv
— a python version manager forked from rbenv and modified for Python.
rbenv
is easy in development. All you need is to create a .ruby-version
file in a directory and from that moment the version specified in this file will be used in this particular directory.
It bundles greatly with Bundler. In fact, bundler
takes care of gem management completely. Each installation of Ruby gets its own installation of bundler. Installation can be configured so that it reuses gems for projects that utilize same Ruby version. Otherwise, gemsets are installed on per-project basis.
rbenv
works by introducing a directory full of small executables called shims
into your path. The path to this directory looks like this: /Users/user/.rbenv/shims
. Each shim is a tiny Bash script that has the exact same name as any Ruby interpreter based tool in your system.
For example, before calling the actual Jekyll
executable, a shim will check the .ruby-version
files and RBENV_VERSION
environmental variable as well as global ~/.rbenv/version
file if other options did not work. Shim will then pull out a correct version of Jekyll according to your specified Ruby version. To be able to do that, the directory with shims is placed first in the $PATH
. This way any call to Jekyll
in our case will be at first directed to a shim.
Let’s take a look at how a user would use rbenv
.
Checking what Ruby versions are available
The whole list is much longer. You can see that beside the versions of the standard interpreter there is a whole bunch of other implementations.
Installing Ruby versions
Any version is installed into the ~/.rbenv directory
. You can later specify which installed version you want to use in your project.
Install bundler
Install gems
Now, if you have a Gemfile
ready, you can perform an installation of all required gems.
Choose Ruby version for project
The order in which Ruby version is checked by rbenv
is perfectly described in the docs. It is hard to rephrase it better:
When you execute a shim, rbenv determines which Ruby version to use by reading it from the following sources, in this order:
The
RBENV_VERSION
environment variable, if specified. You can use the rbenv shell command to set this environment variable in your current shell session.The first
.ruby-version
file found by searching the directory of the script you are executing and each of its parent directories until reaching the root of your filesystem.The first
.ruby-version
file found by searching the current working directory and each of its parent directories until reaching the root of your filesystem. You can modify the .ruby-version file in the current working directory with the rbenv local command.The global
~/.rbenv/version
file. You can modify this file using the rbenv global command. If the global version file is not present, rbenv assumes you want to use the “system” Ruby—i.e. whatever version would be run if rbenv weren’t in your path.
Rbenv installation on MacOS X
A proper installation of ruby environment manager on MacOS X requires only few steps. Most importantly, rbenv
has to be installed through Homebrew, and rbenv init
command has to be called.
Step 1
Install rbenv
brew install rbenv
Note that this also installs ruby-build, so you’ll be ready to install other Ruby versions out of the box.
Step 2
Initialize rbenv
on your OS.
rbenv init
That’s it!
Don’t forget to call rbenv rehash
after installing new gems to give rbenv a change to generate new shims.