This article is intended to be useful for anyone who has a need to deploy–or manage–multiple Ruby installations on a single machine. A reader should have a basic understanding of how Ruby and Ruby gems work within an operating system.
Managing multiple Ruby environments can be a challenge. Ruby is an open-source language, so new releases can be frequent, and those releases can introduce drastic functionality changes. Couple this potential with the use of third-party Gems that may depend on functionality within specific Ruby versions, and your application can quickly find itself struggling to meet all of the dependencies it needs just to execute. RVM (alternately expanded as Ruby enVironment Manager or Ruby Version Manager) tackles this problem head-on by providing a set of command-line tools that allow you to actively control not only the version of Ruby your application uses but also the Gem sets and versions it uses. Below we’ll discuss what RVM is, touching on each of the benefits that it has to offer.
Managing Multiple Ruby Environments
RVM enables you to install multiple versions of the Ruby programming language on a single machine. A native install of the Ruby programming language will install the language’s binaries into a common
bin directory on the operating system; thus any change to those installed binaries will affect all Ruby applications hosted on the machine. Even relatively minor version increases–such as from 2.1.4 to 2.2.1–can introduce changes to the language that break existing language behavior.
RVM allows you to isolate these language binaries into separately-managed environments, which can be used at-will on your system. It accomplishes this isolation by encapsulating each installation into a separate set of directories and dependencies and providing easy-to-use command line tools to quickly switch between versions. RVM handles swapping out all relevant execution paths, environment variables, and installed third-party libraries, allowing developers to focus on developing their applications instead of managing their dependencies.
Why Is RVM Important?
For a single small application, RVM may seem to be overkill. However, once a codebase reaches a certain level of complexity, it may be challenging to track exactly which dependencies the application relies on. Furthermore, as an application grows and leverages various Ruby Gems, these third-party libraries may introduce further dependencies, making a simple version change a complex event fraught with peril. For example, the release of version 2.1.0 introduced a breaking change in the REXML parsers that many Gems use to provide SOAP functionality. This consideration is also crucial for cloud hosted web servers, which may host multiple Ruby applications at once (such as a Resque-based delayed job server, a web server built on Rails, and a Sinatra-based admin console). Getting several different applications with several different sets of dependencies behaving properly can be a full-time job by itself. By encapsulating different Ruby language versions into separate environments, RVM allows the developer to test out new versions, deploy existing applications without worrying about breaking changes, and ensure that application infrastructure management takes as little time as possible.
Resolving Dependency Conflicts
The most obvious benefit gained through the use of RVM is dependency management. By encapsulating the installations of the Ruby programming language into separate command-line-driven environments, you can more easily control version dependencies. RVM, coupled with a Gem management framework like Bundler, can make language-based dependency conflicts a thing of the past–you simply need to verify that there is a version of the Gem you are working with that is compatible with your current installation. Furthermore, using RVM allows you to be confident that only the Gems you need will be installed. Each Ruby environment managed by RVM has its own set of Gems, and as such there is no cross-contamination between apps that may use Gems that affect the Ruby execution environment itself.
In addition to mitigating breaking changes and resolving dependency conflicts, RVM can ease the deployment process for Ruby applications. RVM offers features like “Named Gemsets”, which allow you to quickly and easily specify the dependencies for your Ruby application. Furthermore, Ruby uses a shared cache of gem versions, which reduces the overall disk space used by your Ruby deployment. Finally, RVM works to ensure that all of the specified dependencies are contained entirely within user space, reducing security risks and removing the need to run your application as the root user.
The above article only scratches the surface of the functionality offered by RVM. By using RVM to manage your application’s environment, you can ease deployment concerns, mitigate upgrade issues, and create a reliable set of dependencies for your Ruby application. Coupled with tools like Bundler, RVM makes installing, running, and managing a Ruby application a simple and streamlined process.