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.
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
RVMis 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
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 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
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.
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:
RBENV_VERSIONenvironment variable, if specified. You can use the rbenv shell command to set this environment variable in your current shell session.
.ruby-versionfile found by searching the directory of the script you are executing and each of its parent directories until reaching the root of your filesystem.
.ruby-versionfile 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.
~/.rbenv/versionfile. 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.
brew install rbenv
Note that this also installs ruby-build, so you’ll be ready to install other Ruby versions out of the box.
rbenv on your OS.
Don’t forget to call
rbenv rehash after installing new gems to give rbenv a change to generate new shims.