Installing Ruby the Correct Way
Ruby is an extremely flexible, concise language which boasts a rampant proliferation of libraries and popular frameworks like rails. However, using your system's default ruby to install gems is a quick path into dependency nightmares, as different gems fight to use different versions of the same library.
I'll walk you through how to avoid this using
bundler. At the conclusion, you'll have a better understanding of where ruby lives on your system and you'll also have a stable, flexible ruby installation that can grow with new development while simultaneously providing a bulletproof runtime environment for existing applications and tools.
Questions Before we Begin
What about RVM?
RVM is another tool that purports to alleviate ruby's dependency issues. Having used both
rbenv on OSX, CentOS, and Ubuntu, I find
rbenv to be simpler and more reliable.
I already have some ruby stuff installed. What do I do?
Skip to the "Resetting Your Ruby Installation" appendix at the end of this article. Once you're done, return here and proceed onward, to glory!
In order to install
ruby-build you'll need git and a c compiler. On *nix you can usually get the c toolchain via the
build-essential package. On Mac, the c compiler comes from Xcode or the CLI tools for Xcode, which is a much smaller download.
rbenv or "ruby environment" is a CLI tool that enables you to quickly and easily switch between different rubies installed on your system. We're also going to install ruby-build at the same time.
Ubuntu note: Use
~/.profile instead of
~/.bash_profile below. Also, we'll need to install some dependencies first:
$ sudo apt-get install -y libssl-dev zlib1g-dev libreadline-dev
On to the rest!
$ git clone git://github.com/sstephenson/rbenv.git ~/.rbenv $ git clone git://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build $ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile $ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile $ exec $SHELL -l
ruby-build are now installed. If you'd like to learn more about
ruby-build, refer to @sstephenson's docs -- they're top-notch.
Note I previously recommended adding
RUBY_CFLAGS="-march=native -O3" to your
.bash_profile to make ruby faster, but this caused some issues in later versions of ruby so if you have it there now, take it out.
Installing a ruby
ruby-build are installed you can install a ruby:
$ rbenv install --list
To see a full list of available rubies, or for popular rubies (at the time of writing):
$ rbenv install 1.9.3-p392 $ rbenv install 2.0.0-p0
This will download the source, compile, and install ruby, which will take a few minutes depending on your internet connection and CPU.
When you're done installing rubies, run:
$ rbenv rehash
Switching between rubies
Once at least one ruby is installed, you'll want to set it as the global default so you have a ruby available for doing fun ruby things:
$ rbenv global 1.9.3-p392 $ ruby -v ruby 1.9.3p392 (2013-02-22 revision 39386) [x86_64-linux] $ rbenv global 2.0.0-p0 $ ruby -v ruby 2.0.0p0 (2013-02-24 revision 39474) [x86_64-linux]
If one of your projects requires a specific version of ruby, you can specify this by running
rbenv local VERSION inside the project directory. This will drop a
.ruby-version file into your project, which you can check into source control. That way the version constraint is shared with your team.
You may have noticed that
which ruby doesn't really work anymore since it just points to the rbenv shim. If at any point you're not sure which ruby you're using, type
rbenv version to see.
~/.gemrc with the following contents:
install: --no-ri --no-rdoc update: --no-ri --no-rdoc
This will prevent gem from installing local documentation for each gem it installs which, honestly, you aren't going to read anyway. This makes
gem install run much more quickly and use less space.
Recap So Far
rbenv, compiled a version of ruby using
ruby-build, and set our default ruby. We have
rbenv installed under
~/.rbenv/ and rubies under
~/.rbenv/versions/. We added a
.gemrc to keep our gems lean.
Now that we have ruby, we'll want to install some gems. After all, managing gems is the whole reason we embarked on this journey. Fortunately, ruby-build already installed
gem for us. Now we need
bundler is a tool that allows you to install multiple gem versions side-by-side, and sandboxes each project so that its gem dependencies don't conflict with other projects. Additionally,
bundler allows you to deterministically re-install all of your project depenencies on other developer machines, on production, etc.
$ gem install bundler $ rbenv rehash
We need to run
rbenv rehash any time we install (or remove) an executable like
bundle, etc. or a new ruby version. This makes rbenv rebuild all of the shims used to launch those executables.
Now hop into your project and type:
$ bundle install
bundler will examine your
Gemfile and install all of the listed dependencies.
Note: You'll need to perform
gem install bundler for each version of ruby you install.
The tricky bit with bundler is that we've probably installed several versions of a gem. Which one do we use, and how do we locate it on the
PATH? We don't.
bundler does this for us.
Rather than running
rake from the terminal, we'll run:
$ bundle exec rake
This ensures that the version of rake that's tied to our application is the one that gets executed, even if we have 5 versions on our system. If you're not in a project context (i.e. there's no
Gemfile in your directory), feel free to call
rake from the terminal.
If you're only consuming apps and libs it should be sufficient to run
bundle install and
bundle exec, but if you're writing ruby code you'll probably find the bundler docs very useful.
From now on, just remember to run
bundle exec rake instead of
rake and you'll be completely sandboxed. You'll never have a project stop working because you installed another version of a gem somewhere else.
bundle exec is somewhat verbose, you can create an
bex or similar to make life easier.
$ alias bex="bundle exec" $ bex rake
You can add this to your
~/.bash_profile or similar to make it persistent.
Appendix A: Resetting Your Ruby Installation
"Help! I have a (messed up) ruby installation already!"
The following steps will help you remove rogue rubies from your system. This is potentially destructive. You have been warned.
Check whether rvm is in your path, and if so, remove it from your path and delete rvm using
$ echo $PATH | grep rvm $ rvm implode
If you prefer, you can move
~/.rvm somewhere else to back it up, or
rm -rf ~/.rvm. Restart your terminal after this is done.
Check whether you have more than one ruby installed:
$ which -a ruby
If you're on Mac, remove all rubies except system ruby, which installed at
/usr/bin/ruby. System ruby ships with OS X and removing it will cause Bad Things to happen. If you're on linux, you can safely remove all rubies using your package manager, or
rm if you installed them some other way.
If system ruby is still there when you're done, uninstall all gems from system ruby:
yes | sudo gem uninstall -a --ignore-dependencies `gem list --no-versions`
Restart your terminal so everything is flushed. At this point, you should be able to type:
$ which ruby $ which gem $ gem list --local
/usr/bin/gem on Mac, or nothing on Linux.