Gems

As we learned earlier, a standard Ruby installation includes a large library of code that is always available to your programs (the core library), as well as another large library that your programs can require (the standard library). But wait: there's even more code out there we can use!

What are Gems?

RubyGems, often just called Gems, are packages of code that you can download, install, and use in your Ruby programs or from the command line. The gem command manages your Gems; all versions of Ruby since version 1.9 supply gem as part of the standard installation. So, you probably don't have to do anything special to get RubyGems if you're using a modern version of Ruby.

There are thousands of Gems, and if you're reading this as part of the Launch School curriculum, you may already be familiar with some of them:

  • rubocop: This Gem checks for Ruby style guide violations and other potential issues in your code.
  • pry: This Gem helps debug Ruby programs.
  • sequel: This Gem provides a set of classes and methods that simplify database access.
  • rails: This Gem provides a web application framework that simplifies and speeds web applications development.

The basics of Gems are pretty simple: you can search the RubyGems website to find a Gem you want to install, and then run gem install to install the Gem on your system. Once installed, you can start using most Gems immediately, though you may have to read the documentation first.

A full discussion of Gems is beyond the scope of this book; we focus instead on understanding how Gems interact with Ruby and your system. For more detailed information on how to install, create, and manage Gems, please see the RubyGems documentation. Much of the documentation concerns how to create and update your own or existing Gems, which is probably more than you need right now. However, the RubyGems Basics page provides a nice synopsis of the commands you will use most often, and there's a useful command reference for the gem command.

Gems, Ruby, and your Computer

When you run gem install to install a Gem, what exactly happens? Where does the command find these Gems? Where does it install them on your system? How does Ruby find them? Can you install multiple versions of a Gem? Would you even want to install multiple versions? How do you use a specific version if you have multiple versions installed? Let's examine these questions.

The Remote Library

Since your Ruby installation already includes the gem program (provided you're using version 1.9 or higher of Ruby), all you need to do is find the Gems you want, and install them. Where are these Gems, though? How do you find them?

When you first start using Ruby, someone will usually tell you to install certain Gems. For instance, Launch School tells you to install the rubocop and pry gems; both tools are useful to new (and experienced) Ruby developers. Later, you may learn about other Gems from other people, particularly after searching for tips on how to deal with a particular programming problem. Eventually, though, you will need to search through a remote Gem library. The one you will use most often is the main RubyGems Library. You may also need to search a specialized remote library run by, say, your employer or school.

Note that Gem descriptions at the RubyGems library are often extremely minimal. You will find some additional links on the right hand side of the Gem's main page; the "Homepage" and "Documentation" pages often contain more detailed information. In some cases, you may actually have to read the source code to figure out how to use a Gem. (We will discuss how Gem directories are laid out later on.)

Once you've found a Gem that you want to install, you run gem install GEM_NAME to install the Gem. The gem command connects to the remote library, downloads the appropriate Gems, and installs them. If you specify additional remote libraries, gem also connects to those libraries to find the Gems you want.

The Local Library

When gem installs a Gem, it places the files that comprise the Gem on your local file system in a location where Ruby and your system can find the files and commands it needs. This location is the local library.

Precisely where gem creates the local library depends on several factors, including whether you are using a system Ruby that needs root access, a user maintainable Ruby, the specific Ruby version number, and whether you use a Ruby version manager, e.g., rbenv or RVM. Fortunately, gem knows where to put things, and things just work.

Gems and Your File System

You sometimes need to determine where gem puts things on your system. For example, you may need to look at the source code to better understand how a Gem works. You may also need to diagnose a problem with a Gem not working as expected.

Suppose you want to consult a Gem's source code to get a better idea of what it does. While the source code for Gems is readily available online, you may not always have an internet connection available. So, you may still need to access your local library, even if you aren't having any problems.

If you do look at the source code of a gem on your local system, do not make changes to it. Changes may impact the expected behavior, and you will lose them the next time you update the gem.

So, where do you look? The easiest way is to ask gem to tell you. Run the command:

$ gem env

This prints a longish list of information about your RubyGems installation. Some of the more pertinent information produced by this command looks like this:

RubyGems Environment:
  - RUBYGEMS VERSION: 2.4.8
  - RUBY VERSION: 2.2.2 (2015-12-16 patchlevel 230) [x86_64-linux]
  - INSTALLATION DIRECTORY: /usr/local/rvm/gems/ruby-2.2.2
  - RUBY EXECUTABLE: /usr/local/rvm/rubies/ruby-2.2.2/bin/ruby
  - EXECUTABLE DIRECTORY: /usr/local/rvm/gems/ruby-2.2.2/bin
    ...
  - REMOTE SOURCES:
     - https://rubygems.org/
  - SHELL PATH:
     - /home/ubuntu/.nvm/versions/node/v4.5.0/bin
     - /usr/local/rvm/gems/ruby-2.2.2/bin
     - /usr/local/rvm/gems/ruby-2.2.2@global/bin
     ...

This output is from Cloud9 with the RVM version manager. If your setup is different, your configuration will show different results.

Let's look at some of these settings:

RUBY VERSION

This is the version number of the Ruby associated with the gem command you just ran. Each version of Ruby on your system has its own gem command; if you have multiple versions of Ruby installed, then you have multiple versions of gem installed. Checking the RUBY VERSION is a helpful diagnostic: if you see an unexpected version, you are likely using the wrong version of gem or ruby.

RUBY EXECUTABLE

This is the location of the ruby command that you should use with the Gems managed by this gem command. This information is often useful when RUBY VERSION reveals a gem/ruby mismatch.

INSTALLATION DIRECTORY

This directory is where gem installs Gems by default. Note that the location varies based on the Ruby version number (2.2.2 here). (Under rbenv, you may see two different versions in this name: the first is the major version, the second is the actual version. You can usually ignore the major version.)

Let's look at this structure visually. Note that the following shows the directory structure under RVM; the structure will be different but similar with rbenv or a system ruby. The below diagram shows a RVM-managed Ruby version 2.2.2, with the bundler, freewill, pry, and rubocop gems installed.

Figure 1

$ tree /usr/local/rvm      # the following is partial output
/usr/local/rvm
├── gems
│   └── ruby-2.2.2        # This is the INSTALLATION DIRECTORY for Gems
│       ├── bin
│       │   ├── bundle
│       │   └── rubocop
│       └── gems
│           ├── bundler-1.12.5
│           ├── freewill-1.0.0
│           │   └── lib
│           │       └── freewill.rb
│           ├── pry-0.10.4
│           └── rubocop-0.43.1
└── rubies
    └── ruby-2.2.2
        └── bin
            ├── gem
            ├── irb
            └── ruby
 

This structure shows Ruby 2.2.2 and some associated Gems installed under RVM. In particular, note the locations of the gems directory in this structure. All Gems for Ruby 2.2.2 are installed here. The files are in subdirectories named with the name and version number of the installed Gems. For instance, pry version 0.10.4 is in INSTALLATION DIRECTORY/gems/pry-0.10.4.

Inside each Gem-specific directory, you will find additional subdirectories and files. For example, we show a bit of detail for the freewill 1.0.0 Gem in Figure 1. The lib subdirectory is the most important: this is where your Ruby finds the require files for the Gem. For instance, when you write require 'freewill' in a program, Ruby loads freewill.rb from this lib subdirectory. Note that the Gems are installed within a specific Ruby version; in this way, it's possible to install the same Gem for multiple Rubies because they are installed under the Ruby version-specific directory.

Don't be afraid to look inside these files: so long as you don't modify anything, you're free to read the programs to see how they work, learn more about how to use them, and to diagnose problems with the Gem.

USER INSTALLATION DIRECTORY

Depending on your installation of Ruby and the options you pass to gem, gem may install Gems somewhere in your home directory instead of a system-level directory. This is the location in your home directory that gem uses in such cases.

The structure of the USER INSTALLATION DIRECTORY is the same as the INSTALLATION DIRECTORY.

EXECUTABLE INSTALLATION DIRECTORY

Some Gems provide commands that you can use directly from a terminal prompt; gem places those commands in this directory. In Figure 1, we show the bundler and rubocop executables for Ruby 2.2.2 in the bin subdirectory.

Note that you need to include this directory in your shell PATH variable so that the shell can find these commands. Your Ruby version manager (rbenv or RVM) usually handles this, but it's useful to know where to look if you have problems. (See also SHELL PATH below.)

REMOTE SOURCES

This is the remote library used by this gem installation.

SHELL PATH

The value of your shell's PATH variable; this variable tells your shell which directories it should search to find executable program files. If you have problem with command not found messages or running the wrong versions of programs, this listing may provide valuable clues about where the system looks for your programs.

Note in particular that the list of directories includes /usr/local/rvm/rubies/ruby-2.2.2/bin. We can see from Figure 1 that this directory contains the ruby, irb, and gem commands (it contains other commands as well).

If you don't remember what the PATH is or how to set it, please take some time to review the chapter on the environment in our Introduction to the Command Line book.

Which File Was Required?

While Ruby, Gem, and the Ruby version managers, rbenv and RVM, do a good job of organizing things, you may sometimes run into strange problems that can only happen when you're using the wrong Gem in a program. For example, suppose your program needs a specific feature from version 1.1.1 of a Gem named freewill, but when you try to run the program, you get an error that tells you the feature doesn't exist. How can you find out which version of the Gem your program really loaded?

To determine the Gem version, you need to know the full path name of the file that your program loaded. The easiest way to do this is to insert some debugging code (or a call to binding.pry) in your program shortly after the point where you require the Gem:

puts $LOADED_FEATURES.grep(/freewill\.rb/)

This will print something like this:

/usr/local/rvm/gems/ruby-2.2.2/gems/freewill-1.0.0/lib/freewill.rb

That command searches for any entries in the $LOADED_FEATURES Array that include freewill.rb in the name, and prints all matching entries. With luck, there is just one entry, though sometimes you may have several from which to choose. It's usually easy to choose the right entry though. The resulting name is the path of the file that your program required; by looking at that name, you can see that your program loaded the file from freewill-1.0.0. This tells you that your program loaded version 1.0.0 of the Gem, not version 1.1.1 as needed.

Once you've confirmed that you're using the wrong version of the Gem, you may find that you need to install the desired version, or that you're using the wrong version of Ruby. As we'll see later, this can also be an issue with Bundler.

Multiple Gem Versions

In the previous section, we described an issue where we loaded the wrong version of a Gem. One possible solution to the problem was to install the correct version of the Gem. However, this introduces another opportunity for version-related problems with Gems.

Suppose our system now looks like this:

Figure 2

$ tree /usr/local/rvm      # the following is partial output
/usr/local/rvm
└── gems
    └── ruby-2.2.2        # This is the INSTALLATION DIRECTORY for Gems
        ├── bin
        │   ├── bundle
        │   └── rubocop
        └── gems
            ├── bundler-1.12.5
            ├── freewill-1.0.0
            │   └── lib
            │       └── freewill.rb
            ├── freewill-1.1.1
            │   └── lib
            │       └── freewill.rb
            ├── pry-0.10.4
            └── rubocop-0.43.1

Figure 2 shows that we now have two versions of freewill installed. Let's say that version 1.1.1 is not fully compatible with the older 1.0.0 version. Suppose further that we have another Ruby program that requires the version 1.0.0 of freewill. What happens when this program tries to require 'freewill'?

In this situation, Ruby loads the installed version of the Gem with the most recent version number, namely version 1.1.1. This means trouble for our hypothetical program that needs the older version. This can be addressed in several ways:

  • Provide an absolute path name to require.
  • Add an appropriate -I option to the Ruby invocation.
  • Modify $LOAD_PATH prior to requiring somegem.
  • Modify the RUBYLIB environment variable.

These fixes are all hacks though; they will quickly become unmanageable and an enormous mess and source of bugs. You definitely do not want to go down this road except in the extremely short-term. The right choice is to use Bundler, which we'll discuss later. But first...

Summary

In this chapter, we've learned that RubyGems, or Gems for short, are packages of code that you can download, install, and use in your Ruby programs or from the command line. The gem command manages your Gems.

We've learned how RubyGems are organized on your filesystem, and seen how to deal with some common issues that arise when working with Gems.

We've also briefly touched on the fact that you can install multiple versions of Ruby on your system, and that such multi-version systems take this into account when managing your Gems. However, our coverage was minimal since we need to learn how to put multiple Rubies on your system. We will learn how to do that in the next chapter, Ruby Version Managers.