Published 2022-02-12.
Last modified 2023-12-07.
Time to read: 9 minutes.
ruby
collection.
This article describes how to install Ruby for software development. Ruby is useful for making special-purpose programmable websites and system programming. A working Ruby development setup is necessary for using and developing Jekyll plugins, which are written in Ruby.
The Ruby language is interesting and fun to work with, but the immediate value it provides comes from the large number of high-quality, open-source libraries available for free, which are known as gems.
Standalone or Version Manager?
Because Ruby applications are normally constructed from a collection of Ruby gems, the system on which you installed Jekyll must somehow store those gems. There are several ways to install Ruby plugins, including standalone and virtualized installations using a version manager.
Why Virtualize Ruby?
It is better to use virtualized user- and project-specific Ruby instances instead of working with a system-wide installation of Ruby. This allows you to install and upgrade Ruby packages without using supervisor privileges.
The benefits of virtualized Ruby are similar those provided by
Python venv
and node.js nvm
.
Using multiple virtualized instances allows you to work on many different independent Ruby projects at the same time without package version collisions.
Redundant Virtualization
Some environments should not switch between multiple Ruby versions. Container images meant for either Ruby development or production should just use a standalone Ruby installation.
For example, using virtualized Ruby in a docker
image or a VM just adds complexity and overhead.
You should choose between docker
and virtualized Ruby;
avoid using both for the same project.
Use Docker & VMs Appropriately
I believe docker
is oversold.
It adds unnecessary complexity to software projects.
Instead of virtualizing the entire software environment,
as docker
attempts to do,
virtualize the Ruby programming environment as described in this article.
Your system will run faster, plus setup and maintenance will be simpler.
I think docker
has been pushed hard in the media because it is a gateway technology to
PaSS.
This is a trend that PaSS vendors like AWS and Azure want to encourage, but
customers are pushing back.
Ruby Installation Options
Various popular choices for installing the Ruby language exist that follow best practices. The less popular choices have smaller user communities; follow the path less traveled at your peril.
The JetBrains 2022 Ruby Survey found that only 5% of Ruby developers did not use a Ruby version manager:
Let’s briefly consider three of the available options:
-
Install the current version of Ruby standalone, without a Ruby version manager.
This option might be most appropriate for a production Linux system that has the minimum amount of software installed.
It is the simplest option for Ubuntu and WSL.
This option is problematic for Macs, however, so read on for a better option.
If you use this option, you will have to set the
GEM_HOME
environment variable and add$GEM_HOME/bin
to thePATH
. The details are explained below. -
As a regular user using the
rbenv
Ruby version manager. This is by far the most popular option for software developers, in part because it is lightweight and also because it works so well on Linux and Mac. This option does not require you to mess around with environment variables.
If you use a Mac, this option provides the best experience.
This article explains all the details. -
As a regular user using the
rvm
version manager.rvm
has more features thanrbenv
and is easier to install, but it is older and has features that are no longer required with modern versions of Ruby.rvm
also redefines some system commands, which can be awkward and confusing. Like therbenv
option,rvm
does not require you to mess around with environment variables. This article will not discussrvm
any further.
Ruby Packages
The official Ruby installation instructions are inconsistent across different OSes. For example, following the Ubuntu installation instructions for Ruby also installs the Ruby system headers, while the macOS instructions do not mention the subject, even though they are required. Fear not, dear reader; I will tell you all in this article.
Regardless of how you install Ruby,
gems should never be installed by using elevated user privileges
(in other words, without using sudo
).
Standalone Ruby
This is how to perform the first option described above:
installing the current version of Ruby without a version manager.
I have done my best to discourage you from following this path,
and to motivate you to install rbenv
instead.
WSL, Ubuntu and Friends
These instructions apply if your computer has an Ubuntu-derived Linux distro, such as Ubuntu Desktop, Edubuntu, Kubuntu, Lubuntu, Budgie, Cinnamon, Kylin, MATE, Ubuntu Studio, Unity, and Xubuntu. They also apply equally well if have a Windows computer with WSL installed, and one of the Ubuntu flavors just mentioned is installed in WSL.
The apt
package manager
documentation for the ruby-full
package lists three other packages related to installing Ruby,
all of which are dependencies of ruby-full
.
This means those packages automatically get installed when ruby-full
is installed.
Some of these dependencies are redundant;
for example, ruby-dev
is a direct dependency of ruby-full
and a transitive dependency because it is also a dependency of ruby
.
That is good because ruby-dev
needs to be installed.
ri
- Ruby Interactive reference
ruby
- Includes the interpreter for the Ruby language
ruby-dev
- Contains header files for compiling extension modules for Ruby
Ubuntu 23.04 (Lunar Lobster) Update:
The new standard Ruby debugger for Visual Studio Code
(debug
)
requires that the libyaml-dev
package also be installed, or psych
,
which is a transitive dependency of debug
, will not install.
The Ruby community has standardized around using git
as a source code management tool.
For example, the rake
command and bundler
(discussed below)
both have special considerations for git
repositories.
In the following incantation, I ensure that git
is installed with Ruby for this reason.
$ yes | sudo apt install git ruby-full libyaml-dev
Mac
Installing Xcode and the command line tools
needs to be done first because that installs gcc
,
which is required for building dependencies.
$ xcode-select --install $ sudo xcodebuild -license
You will also need to install the XCode command-line tools and the header files available from XCode:
- Start XCode.
- Select Preferences / Downloads.
- Click on Command Line Tools and install them.
- Restart the computer.
Install Homebrew, rbenv
and Ruby:
$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" $ brew update $ brew install rbenv rbenv-gem-rehash
GEM_HOME and PATH
This section continues the discussion of how to set up a standalone Ruby instance without a version manager.
The official installation instructions describe how to install Ruby,
but do not mention setting GEM_HOME
or
the need to include $GEM_HOME/bin
into the PATH
.
If you opt for a Ruby version manager such as rbenv
, described next,
there is no need to do the following.
- Create a directory to hold the gems:
Shell
$ mkdir $HOME/.gems
- Add the following to
~/.bashrc
,~/.bash_profile
or~/.zshrc
:
~/.bashrc, ~/.bash_profile or ~/.zshrcexport GEM_HOME=$HOME/.gems export PATH=$GEM_HOME/bin:$PATH
Rbenv
Now we can discuss the second option:
using the rbenv
version manager to install and
maintain Ruby instances of various versions.
Rbenv
works well,
and I strongly urge you to consider using it for your daily Ruby programming needs.
A feature that delighted me the first time I encountered it:
If the file .ruby-version
exists in a top-level project directory,
rbenv
automagically ensures that version of Ruby is used for the project.
For example, to run Jekyll with Ruby 3.1.0 for a given website,
the file .ruby-version
just needs to exist in the top-level
git directory for the source code, as shown:
$ cat .ruby-version 3.1.0
If the required version of Ruby is not available, an error is issued and execution stops:
rbenv: version '3.1.0' is not installed (set by /var/
Installing Rbenv
If you opted to install Ruby using rbenv
on any platform, including Linux and Mac,
follow the
rbenv
official installation instructions.
Unfortunately, I found a few errors and continuity gaps in the instructions.
The following is an annotated transcript of what I did to install on WSL/Ubuntu,
supplemented with notes for Mac.
debug
)
requires that the libyaml-dev
package also be installed, or psych
,
which is a transitive dependency of debug
,
will not install.
$ yes | sudo apt install git rbenv ruby-dev libyaml-dev Reading package lists... Done Building dependency tree... Done Reading state information... Done rbenv is already the newest version (1.1.2-1). 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Ubuntu bash:
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
Mac bash:
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
Zsh, all platforms:
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.zshrc
You still need to install ruby-build
before you can install Ruby itself, so please read on!
Using Rbenv
Rbenv
builds Ruby using gcc
instead of installing a prebuilt version.
As you have just learned, Ruby will be installed into ~/.rbenv/versions
.
Unlike installing standalone Ruby,
when using rbenv
to install Ruby, there is no need to set GEM_HOME
.
Instead, the location of the gems is inferred by the currently active Ruby instance.
The help information provided by man
about rbenv
is rather limited:
$ man rbenv RBENV(1) RBENV(1)
NAME rbenv - Simple Ruby Version Management
USAGE Initialize rbenv for your acccount:
$ rbenv init $ echo 'eval "$(rbenv init -)"' >> ~/.bashrc # restart your shell after this
Install different Ruby interpreters (requires the ruby‐build package):
$ rbenv install 2.4.0
Switch between different Ruby interpreters:
$ rbenv global 2.4.0 $ ruby -v ruby 2.4.0p0 (2016-12-24 revision 57164) [x86_64-linux] $ rbenv global system $ ruby -v ruby [whatever version of Ruby Debian provides by default]
The original rbenv README with a more comprehensive documentation, including all of the available commands, is available at /usr/share/doc/rbenv/README.md.gz
ABOUT This manual page was written for the Debian system by Antonio Terceiro <terceiro@debian.org> and may be used by others.
2020‐12‐16 RBENV(1)
The rbenv
command-line help is more useful:
$ rbenv help Usage: rbenv <command> [<args>]
Some useful rbenv commands are: commands List all available rbenv commands local Set or show the local application-specific Ruby version global Set or show the global Ruby version shell Set or show the shell-specific Ruby version install Install a Ruby version using ruby-build uninstall Uninstall a specific Ruby version rehash Rehash rbenv shims (run this after installing executables) version Show the current Ruby version and its origin versions List installed Ruby versions which Display the full path to an executable whence List all Ruby versions that contain the given executable
See `rbenv help <command>' for information on a specific command. For full documentation, see: https://github.com/rbenv/rbenv#readme
Unfortunately, when you attempt to get a listing of all the available rbenv
commands,
you get this pathetic excuse for a help message:
$ rbenv help commands Usage: rbenv commands [--sh|--no-sh]
List all available rbenv commands
I happen to know that the first command that you should run is rbenv init
.
Lets see its help message:
$ rbenv help init Usage: eval "$(rbenv init - [--no-rehash] [<shell>])"
Configure the shell environment for rbenv
Again, not the most informative help message.
Now bravely go ahead and initialize rbenv
, even though we are not quite sure what it does:
$ rbenv init # Load rbenv automatically by appending # the following to ~/.bashrc or ~/.bash_profile: export PATH="$HOME/.rbenv/shims:$PATH" source /usr/lib/rbenv/completions/rbenv.bash eval "$(rbenv init -)"
Contrary to what the instructions say, there is no need to put the following lines into
~/.bashrc
or ~/.bash_profile
.
I will show you why in a moment.
export PATH="$HOME/.rbenv/shims:$PATH" source /usr/lib/rbenv/completions/rbenv.bash
Also, contrary to what the instructions say, there is no need to open another shell to run the magic incantation. I call it magic because it is not obvious what the incantation does or why it is needed. Simply type:
$ eval "$(rbenv init -)"
It is easy enough to learn what the incantation does; just run it without evaluating the output:
$ rbenv init - export PATH="/home/mslinn/.rbenv/shims:${PATH}" export RBENV_SHELL=bash source '/usr/lib/rbenv/libexec/../completions/rbenv.bash' command rbenv rehash 2>/dev/null rbenv() { local command command="${1:-}" if [ "$#" -gt 0 ]; then shift fi
case "$command" in rehash|shell) eval "$(rbenv "sh-$command" "$@")";; *) command rbenv "$command" "$@";; esac }
Now we know that the magic incantation generates a bash script that does the following:
- Adds
~/.rbenv/shims
to thePATH
- Reads in bash tab completions for
rbenv
- Defines a bash function called
rbenv
that shadows the actualrbenv
command
Placing the magic incantation into ~/.bashrc
or ~/.bash_profile
causes the script to be regenerated each time a shell is opened.
Go ahead and do that.
Now you know why I said that the earlier instruction to place the following two lines into
~/.bashrc
or ~/.bash_profile
is redundant
because the magic incantation does that.
export PATH="$HOME/.rbenv/shims:$PATH" source /usr/lib/rbenv/completions/rbenv.bash
Call the Doctor
Run the Doctor script
to verify all is well with rbenv
:
$ curl -fsSL \ https://github.com/rbenv/rbenv-installer/raw/main/bin/rbenv-doctor \ | bash Checking for `rbenv' in PATH: /usr/bin/rbenv Checking for rbenv shims in PATH: OK Checking `rbenv install' support: not found Unless you plan to add Ruby versions manually, you should install ruby-build. Please refer to https://github.com/rbenv/ruby-build#installation Counting installed Ruby versions: none There aren’t any Ruby versions installed under ’/home/mslinn/.rbenv/versions’. You can install Ruby versions like so: rbenv install 2.7.1 Checking RubyGems settings: OK Auditing installed plugins: OK
Ruby-build
Ruby-build
is a command-line utility that makes it easy to install virtually any version of Ruby from source.
Ruby-build
is available as a plugin for rbenv
that provides the rbenv install
subcommand.
Ruby-build
also installs a standalone command of the same name.
I find that installing ruby-build
as an rbenv
plugin is the most flexible and portable option.
The following commands can be executed from any directory.
$ echo "$(rbenv root)" /home/mslinn/.rbenv $ mkdir -p "$(rbenv root)"/plugins $ ls "$(rbenv root)" plugins shims versions $ ls "$(rbenv root)"/shims bundle bundler erb gem irb racc racc2y rake rbs rdbg rdoc ri ruby typeprof y2racc $ git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build Cloning into '/home/mslinn/.rbenv/plugins/ruby-build'... remote: Enumerating objects: 12063, done. remote: Counting objects: 100% (756/756), done. remote: Compressing objects: 100% (304/304), done. remote: Total 12063 (delta 481), reused 626 (delta 402), pack-reused 11307 Receiving objects: 100% (12063/12063), 2.54 MiB | 14.37 MiB/s, done. Resolving deltas: 100% (7948/7948), done.
To upgrade Ruby-build
at a later time,
run the following from any directory:
$ git -C "$(rbenv root)"/plugins/ruby-build pull
To list all available versions of Ruby:
$ rbenv install --list 3.0.6 3.1.4 3.2.2 jruby-9.4.5.0 mruby-3.2.0 picoruby-3.0.0 truffleruby-23.1.1 truffleruby+graalvm-23.1.1 Only latest stable releases for each Ruby implementation are shown. Use 'rbenv install --list-all / -L' to show all local versions. 8 lines have been placed on the clipboard.
This is the help message of the ruby-build
command:
$ ruby-build Usage: ruby-build [-kpv] <definition> <prefix> ruby-build --definitions ruby-build --version
-k/--keep Do not remove source tree after installation -p/--patch Apply a patch from stdin before building -v/--verbose Verbose mode: print compilation status to stdout -4/--ipv4 Resolve names to IPv4 addresses only -6/--ipv6 Resolve names to IPv6 addresses only --definitions List all local definitions -l/--list List latest stable releases for each Ruby --version Show version of ruby-build
According to the above documentation, the following incantation should show you all available versions of Ruby. However, I will now demonstrate that that the information it provides is usually out-of-date:
$ ruby-build -l 2.6.10 2.7.6 3.0.4 3.1.2 jruby-9.3.4.0 mruby-3.0.0 rbx-5.0 truffleruby-22.1.0 truffleruby+graalvm-22.1.0
The output of rbenv install --list
should theoretically match the output of ruby-build -l
;
however, it does not.
The reason is because ruby-build
was cloned from a git repository,
so it is by definition completely up-to-date,
while the rbenv
Ubuntu package can lag considerably behind.
rbenv install --list
command instead of ruby-build -l
Installing Latest Stable Ruby
Now we can use rbenv
to install ruby
.
Use the following incantation to install the latest stable version of Ruby:
$ rbenv install $(rbenv install -l 2>/dev/null | sed -ne 3p)
Installing A Specific Ruby Version
The following installs Ruby version 3.1.0.
$ rbenv install 3.1.0 Downloading ruby-3.1.0.tar.gz... -> https://cache.ruby-lang.org/pub/ruby/3.1/ruby-3.1.0.tar.gz Installing ruby-3.1.0... Installed ruby-3.1.0 to /home/mslinn/.rbenv/versions/3.1.0
The build took 5 minutes, 11 seconds on a fast laptop with an M.2 SSD.
Activating A Ruby Version
Now that we have installed a Ruby interpreter, we need to activate it before it will be used.
Before doing anything, please notice that we are still using the system version of Ruby:
$ echo $GEM_HOME $ gem env home # System version of Ruby /var/lib/gems/2.7.0
The following command sets Ruby 3.1.0 as the default version of Ruby. This setting is persistent.
$ rbenv global 3.1.0 $ rbenv rehash $ gem env home /home/mslinn/.rbenv/versions/3.1.0/lib/ruby/gems/3.1.0
Now two important gems can be installed into the currently active Ruby instance:
bundler
and rake
.
$ gem install bundler rake Fetching bundler-2.3.8.gem Successfully installed bundler-2.3.8 Parsing documentation for bundler-2.3.8 Installing ri documentation for bundler-2.3.8 Done installing documentation for bundler after 0 seconds Successfully installed rake-13.0.6 Parsing documentation for rake-13.0.6 Installing ri documentation for rake-13.0.6 Done installing documentation for rake after 0 seconds 2 gems installed
Lets discover information about these gems:
$ gem info -b rake bundler
*** LOCAL GEMS ***
rake (13.1.0) Authors: Hiroshi SHIBATA, Eric Hodel, Jim Weirich Homepage: https://github.com/ruby/rake License: MIT Installed at: /home/mslinn/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0
Rake is a Make-like program implemented in Ruby
*** REMOTE GEMS ***
rake (13.1.0) Authors: Hiroshi SHIBATA, Eric Hodel, Jim Weirich Homepage: https://github.com/ruby/rake
Rake is a Make-like program implemented in Ruby
*** LOCAL GEMS ***
bundler (2.4.22, 2.4.20, 2.3.7) Authors: André Arko, Samuel Giddins, Colby Swandale, Hiroshi Shibata, David Rodríguez, Grey Baker, Stephanie Morillo, Chris Morris, James Wen, Tim Moore, André Medeiros, Jessica Lynn Suttles, Terence Lee, Carl Lerche, Yehuda Katz Homepage: https://bundler.io License: MIT Installed at (2.4.22): /home/mslinn/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0 (2.4.20): /home/mslinn/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0 (2.3.7, default): /home/mslinn/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0
The best way to manage your application's dependencies
*** REMOTE GEMS ***
bundler (2.4.22) Authors: André Arko, Samuel Giddins, Colby Swandale, Hiroshi Shibata, David Rodríguez, Grey Baker, Stephanie Morillo, Chris Morris, James Wen, Tim Moore, André Medeiros, Jessica Lynn Suttles, Terence Lee, Carl Lerche, Yehuda Katz Homepage: https://bundler.io
The best way to manage your application's dependencies
Ruby Development Components
Common components for Ruby development include the two gems we just installed:
-
Bundler
provides the
bundle
command, which lets you define the libraries that a project needs. It automatically resolves version conflicts and downloads all necessary gems from the sources you provide. -
Rake
is amake
-like program implemented in Ruby. Tasks and dependencies are specified in standard Ruby syntax. - A testing framework:
rspec
,minitest
,bacon
,test::unit
,cucumber
,capybara
, etc.
If you are developing a web app, you will likely need to use one each of the following:
-
An app server:
unicorn
,puma
,thin
,mongrel
-
Web server:
nginx
, Apachehttpd
- Web framework: Ruby on Rails, Sinatra, etc.
Speeding up Gem Installations
New gems can be extremely slow to install.
You can accelerate the process by ignoring
ri
and
rdoc
information.
To accomplish that, create the file ~/.gemrc
as follows.
install: --no-ri --no-rdoc update: --no-ri --no-rdoc
Of course, that means you will not have documentation locally available for the gems that you install or update after that.
About the Author
I, Mike Slinn, have been working with Ruby for a long time now. Back in 2005, I was the product marketing manager at CodeGear (the company was formerly known as Borland) for their 3rd Rail IDE. 3rd Rail supported Ruby and Ruby on Rails at launch.
In 2006, I co-chaired the Silicon Valley Ruby Conference on behalf of the SD Forum in Silicon Valley. As you can see, I have the t-shirt. I was the sole chairman of the 2007 Silicon Valley Ruby Conference.
Several court cases have come my way over the years in my capacity as a software expert witness. The court cases featured questions about IP misappropriation for Ruby on Rails programs. You can read about my experience as a software expert if that interests you.
I currently enjoy writing Jekyll plugins in Ruby for this website and others, as well as Ruby utilities.