How I configure my Ruby development environment
I saw someone Tweet something like “What’s the Ruby equivalent of Python’s virtualenv?”. Having been on the other side of that particular coin, I thought I’d take a moment to explain what I think is a pretty typical Ruby development environment. There are many ways to skin this cat. This is how I do it. YMMV.
How to manage multiple Ruby versions
rbenv install x.x.x
where “x.x.x” is a version of Ruby chosen from those available via
To get the latest releases of Ruby, simply:
brew upgrade ruby-build
and then use rbenv to install the new version you’re after.
How to specify a Ruby version for your project
In the root of your project, create a “.ruby-version” file like this:
rbenv local x.x.x
Where “x.x.x” is the version of Ruby (chosen from “rbenv versions”) that you want your project to run on. The “.ruby-version” file seems to work with rvm, chruby and others as well.
With this file in place, rbenv will switch to the specified version of Ruby when you change into your project’s directory.
How to manage gems with Bundler
For every version of Ruby we have installed, we’ll need to install Bundler to manage dependencies. If you’re skeptical about this, just go with it for now.
Bundler is itself a gem and can be installed with:
gem install bundler
With Bundler installed, we can create a Gemfile to specify our gems and our ruby version (again) and we’re off to the races.
A simple Gemfile might sit in the root of our project and look like this
gem 'rails', '~> x.x.x'
We can then install Rails like this:
This will indeed install Rails (and all it’s dependencies). We can invoke Rails commands like this:
bundle exec rails --version
Because we’re using Bundler to manage our Gem dependencies, we need to use bundler to invoke the gems it’s installed, hence the “bundle exec”.
Using binstubs to avoid typing “bundle exec” all the time
If, instead of simply typing “bundle install” we instead type the following:
bundle install --path .bundle/gems --binstubs .bundle/bin --jobs n
…we’ll install our dependencies into the root of our project a the path .bundle/gems, and we’ll also create “binstubs” for each dependency in the similarly located .bundle/bin directory.
By installing dependencies to ./bundler/gems with the — path flag, we ensure that each project has it’s own, isolated copy of each dependency. If for whatever reason we chose to mess with this project’s version of Rails (try “bundle open rails” to make changes), we won’t affect another project running the same version of Rails.
By using the — binstubs flag and specifying a directory, we tell Bundler to create shortcuts to any executables a dependency may provide and to put them in .bundle/bin for easy access later.
What’s more, with the “ — jobs n” flag, we can install n dependencies at a time (set n to the number of cores your machine has — mine is 4). Save the above as an alias. Something like this works for me:
alias b='bundle install --path .bundle/gems --binstubs .bundle/bin --jobs 4'
Now, instead of “bundle install”, in the root of our project we can just run:
… and all our dependencies will install in the right way to the right place.
If we then export ./bundle/bin (the place we saved all those shortcut executables to) to the start of our $PATH (in your .bashrc file or similar), we can avoid having to “bundle exec” everything:
With that in place we can now just do:
…and we’re all set. The local version of each executable is always found first, as ./.bundle/bin is the first place your shell will look.
Specifying a Ruby version with Bundler
Bundler allows specifying a Ruby version as well. Seeing as the next person to run your code may or may not use a tool the respects the “.ruby-version” file, we should specify a Ruby version in our Gemfile, too. This will ensure our dependencies are compiled using the version of Ruby we expect, and throw an error if the specified version of Ruby is not being used. In our Gemfile above we did this with the line:
Where “x.x.x” is the version of Ruby we want to compile our dependencies against.
This is how I’ve set up my Ruby development environment for the last few years. I hope it helps you come to terms with yours.
Questions, comments, suggestions and (constructive) criticisms all welcome.