Wednesday, December 25, 2013

Install ruby

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:

~/.gemrc
1
2
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.

Shell
yum --enablerepo=rpmforge,epel,remi -y install gcc make zlib zlib-devel openssl-devel zsh
 
cd /usr/local
git clone git://github.com/sstephenson/rbenv.git rbenv
mkdir rbenv/shims rbenv/versions
chgrp -R groupname rbenv
chmod -R g+rwxXs rbenv
git clone git://github.com/sstephenson/ruby-build.git ruby-build
cd ruby-build
./install.sh
 
cat << _ZSHCONF_ >> ~/.zshrc
## rbenv config
export RBENV_ROOT="/usr/local/rbenv"
export PATH="/usr/local/rbenv/bin:${PATH}"
eval "$(rbenv init -)"
_ZSHCONF_
 
rehash
 
rbenv install 1.9.3-p392
 
rbenv global 1.9.3-p392
 
rehash