What is a Ruby Gem?

Morganne Gagne
6 min readJan 18, 2018

--

When I first learned about Ruby Gems, they seemed quite magical. By running bundle install I could somehow acquire these magic gems that would make my code do all sorts of things that seemed way beyond my Week 1 Flatiron student abilities. Akin to “item boxes” in Mario Kart, gems seem to bestow super powers upon the user.

Ruby Gems give you magic powers!

I intend to use my blog to delve deeper into programming concepts that pique my curiosity and that I do not fully understand. For my first blog post, I am going to debunk the mystical, magical nature of Ruby gems.

What is a Ruby Gem?

No, Ruby gems are not magic. They are simply open source libraries that contain Ruby code and are packaged with a little extra data . Using a gem allows a programmer to use the code within the gem in their own program, without explicitly inserting that code.

Gems can be used for all sorts of purposes, and you can explore different gems at https://rubygems.org/. To get a better idea of what gems can do, here are a couple popular gems and their functionality:

  • Bundler — Provides a consistent environment for Ruby projects by tracking and installing the exact gems and versions that are needed. It is the #1 downloaded gem of all-time, but more on Bundler later.
  • RSpec — A testing framework that supports Behavior Driven Development for Ruby.
  • Devise — Devise works with authentication. For any website that needs to user log-in’s, Devise handles sign in, sign up, reset password, etc.
  • JSON — Provides an API for parsing JSON from text.
  • Nokogiri — Provides HTML, XML, SAX, and Reader parsers with XPath and CSS selector support.
  • Rails — Rails is a gem! Rails provides the fullstack framework that allows Ruby to be transformed into web applications.

Installing Gems

Today, using gems is easy! Installing gems locally is as simple as a single command: gem install [gem_name] . The install command fetches the code, downloads it to your computer, and installs the gem and any necessary dependencies. Finally, it will build documentation for the installed gems.

Installing bundler only requires installing 1 gem

While some gems, like Bundler, only require 1 gem to be installed, other gems have dependencies that require the installation of multiple gems:

Installing Draper also required the installation of the Request Store and the Active Model Serializers gems

To see all locally installed gems, use the command, gem list .

Using Gems

Now, more importantly, how can we use our installed gems? Well, it depends on the type of gem. Some gems, like Rails, are stand-alone Ruby programs that you can run from the command.

Others are relatively useless on their own, but incredibly helpful when used within a project. To use a gem from within your code, it is necessary to require it first at the top of the file — require 'gem_name' . For example, Pry has quickly become one of my favorite gems when working on projects. My code i̶s̶n̶’̶t̶ ̶a̶l̶w̶a̶y̶s̶ is almost never correct when I first write it, and Pry makes debugging far more efficient and a little less painful. This past week, we learned about APIs and needed Pry and a couple of other gems to complete the project.

While gems are very straightforward if you only need them on your computer, they become slightly more complicated if you want to distribute or publish your project. Anyone else who runs your project will need to have all the necessary gems and the correct versions installed on their computer. Thankfully, we have RubyGems and Bundler which streamline the process.

RubyGems is the Framework that Simplifies Gem Sharing

Part of the magic of gems is that we can all use them, and RubyGems is the package manager that makes that possible. It provides a standard format for distributing Ruby gems, manages the installation of gems, and a server for distributing them. RubyGems wasn’t released to the public until March 14, 2004 (Pi Day! π) Although RubyGems has existed since Ruby 1.8, it was not a part of the standard Ruby distribution until Ruby 1.9. So for Ruby newbies, like myself, RubyGems is automatically installed on your computer when you install Ruby.

How did Rubyists ever live without RubyGems?

Life was a lot harder. If you want the full story, I would highly recommend watching André Arko’s presentation “How does Bundler work, anyway?” from the RailsConf 2015. Here’s my summarized version:

Loading coding started with require , and using require is essentially the same as inserting the code into your file. In its simplest form, it is a method that extracts code from the argument file.

def require(filename)
eval File.name(filename)
end

Require allows users to load any local code, by searching the user’s $LOAD_PATH for the file. $LOAD_PATH is a global variable and an array of absolute paths. As long as the code’s directory is located somewhere within the $LOAD_PATH, require will be able to find it.

While require is great for local code, what if you wanted to get code from someone else? It was a tedious process — you would need to find the code, download it, save it somewhere on your computer and add that somewhere to the $LOAD_PATH.

As a result, setup.rb evolved to ease the process. Setup.rb (which is still around today) is a generic installer for Ruby scripts and libraries. It was a major improvement over require because it copied all of the Ruby files into a directory that was already in the $LOAD_PATH. Developers are inherently lazy, and setup.rb saved us a couple steps. However, setup.rb had its own set of issues. There was no version tracking and no way to uninstall a program! The only definitive way to know what version you had was to write down the version number at installation. As you can imagine, using libraries was a bit of a disaster.

In 2004, RubyGems came to the rescue! Now other people’s code, or gems, could be installed or uninstalled with a single command! It was revolutionary. RubyGems had another trick up its sleeve — it could handle different versions of software, and every version was kept in its own separate folder.

Bundler Solves Gem Dependencies

As incredible as RubyGems seemed, it had one inherent flaw. If you wanted to share a project, how did you ensure that a new user had all the necessary gems?With RubyGems’ current set-up, if a developer ran gem install foo and started using a new gem in the application, other developers on the project would need to be told to run gem install foo . Certain gems could only work with certain versions of other gems, and it became increasingly difficult to coordinate gem and version dependencies.

Alas, we arrive at Bundler! Bundler exists to solve the issue of gem version dependency by tracking and installing the exact gems and versions that are needed. Bundler works through a Ruby gem’s “gemfile” which tells Bundler which gems to look for and where to look for them. https://rubygems.org is the default source, but if gems exist on a private server, that source can be overwritten for those specific gems.

Example Gemfile — Source: http://bundler.io/rationale.html

After installing the required gems (if your computer doesn’t already have them), Bundler will write all of the gems and versions that it installed to another file, Gemfile.lock. This lock file makes it possible to install the exact same versions on to every machine that runs the application.

Using Bundler is simple. First, it is necessary to install it, and because Bundler is a gem itself, we can do so with: gem install bundler . With Bundler installed, you can use any gem in your own project in 2 steps:

  1. Add the gem to a Gemfile in in your project’s root
  2. Run bundle install in your terminal

For more Bundler specifics, check out http://bundler.io/.

--

--