The innards of a RubyGem
Tags: ruby, beginners
Published: 2018-10-23 13:26:21

---
title: The innards of a RubyGem
description: Share code with yourself or others by utilizing the RubyGems ecosystem.
cover_image: https://blog.appsignal.com/images/blog/2018-10/gems.jpg
tags: ruby, beginners
published: true
canonical_url: https://blog.appsignal.com/2018/10/23/the-innards-of-a-ruby-gem.html
---

Gather ’round children, and let grandpa recount the ways of the old days when life was hard, and installing gems was a headache-inducing, hair-pulling, teeth-gritting ordeal.

Back when I was just starting in Ruby, there was no Bundler and gems had to be installed the hard way. In Rails, this meant running `rake gems:install` a million times, fixing occurring bugs along the way, until the command passed with no errors. Today, we’re going to create a gem the old school way, after looking into what gems are and how they work.

# Gems, What Are They?

RubyGems are an easy way to extend your own code with functionality written by other people. For example, instead of writing your own authentication/authorization code, you can use [Devise](https://rubygems.org/gems/devise), or if you want to re-size uploaded images you can use [CarrierWave](https://rubygems.org/gems/carrierwave). This allows you to write reusable code that you can share with other people.

# But How Do They Work?

In its most basic form, a gem is nothing more than a zipped-up directory containing code and a `<name>.gemspec` file. This `.gemspec` file contains metadata about the gem such as its name, what files to load and its dependencies.

The `gem install` or `bundle` command downloads the zip file from the source and extracts it to your hard drive. You can find out where a gem is located by running `bundle info <gem name>` or by directly opening the gem directory by running `bundle open <gem name>`.

To load the gem into your application, Rubygems [monkey-patches](https://github.com/rubygems/rubygems/blob/481e8aca99d162e3c85873d47b7a2cb8a0fbc394/lib/rubygems/core_ext/kernel_require.rb#L20-L133) the `require` function in the `Kernel` class. It first tries to read the file from disk and if that doesn’t work, it then tries to resolve the file in each of the gems on your system. Once it finds the file in a gem it “activates” the gem by adding it to the load path.

If you use Bundler, it adds [each specific gem to the load path](https://github.com/bundler/bundler/blob/477115c0699c89a940171c4911dbc2b060054f84/lib/bundler/runtime.rb#L12-L51) during the `setup` call. This saves Rubygems the hassle of trying to resolve the paths. It also prevents Ruby from loading a different version of the gem than is selected in the Gemfile(.lock).

# How Can I Make One?

The easiest way to create your own gem is to use [Bundler](https://bundler.io/v1.13/guides/creating_gem) to generate a gem scaffold. This includes a proper directory structure, license, code of conduct and a test environment for the gem.

However, today we’re going to create our own minimalistic gem with just two files, one containing the code and a `gemspec` file that contains the metadata. Our gem will greet the user when called. Let’s start by creating a directory for our gem.

```bash
mkdir howdy
cd howdy
```

In this directory, we’ll create a `lib` folder that will contain the code and a `howdy.gemspec` file that will contain the metadata. It should look something like this:

```bash
tree
.
├── howdy.gemspec
└── lib
    └── howdy.rb
```

Our howdy gem has the following code:

**lib/howdy.rb**

```ruby
class Howdy
  def greet
    "howdy!"
  end
end
```

A minimalistic `howdy.gemspec` file contains information about the version, author, etc. It also specifies the files to keep when building a gem. This prevents the users of the gem from having to download unnecessary files such as tests and other files that aren't needed to run the gem code.

```ruby
Gem::Specification.new do |spec|
  spec.name          = "howdy"
  spec.version       = "0.0.1"
  spec.authors       = ["Robert Beekman"]
  spec.email         = ["robert@example.com"]

  spec.summary       = %(Greets the user)
  spec.description   = %(Howdy is a gem that greets the user when called)
  spec.license       = "MIT"

  spec.files         = ["lib/howdy.rb"]
end
```

To build the gem we can use the `gem build howdy.gemspec` command. It generates a `howdy-0.0.1.gem` file containing your code. To make the gem available to other people, you can publish it to [rubygems.org](https://rubygems.org) with the `gem publish` command.

## Recap
These are the steps needed to create and publish a very basic gem. We hope you enjoyed us diving into the archeology of gems, and the old school way of making them. As mentioned before this was for educational purposes; we recommend using [Bundler](https://bundler.io/v1.13/guides/creating_gem) to generate a gem scaffold in today's world.

Peace out, youngsters! If you have any ideas, questions or comments, please don't hesitate to leave a comment.