Installing Ruby the Correct Way
Published 2013-03-27
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 rbenv
, ruby-build
, and 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 rvm
and 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!
Prerequisites
In order to install rbenv
and 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.
Install rbenv
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
rbenv
and ruby-build
are now installed. If you'd like to learn more about rbenv
or 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
Once rbenv
and 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.
Configure Gem
Create ~/.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
We've installed 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.
Install bundler
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
.
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 rake
, 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.
Using bundle exec
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.
Aliasing
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.
Since typing bundle exec
is somewhat verbose, you can create an alias
like be
or 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 implode
.
$ 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
And see /usr/bin/ruby
and /usr/bin/gem
on Mac, or nothing on Linux.