How to create a gem from scratch?
Tags: tech, ruby, rails, webdev
Published: 2019-05-05 22:25:09

---
title: How to create a gem from scratch?
published: true
tags: tech,ruby,rails,webdev
canonical_url: https://medium.com/@nisevi/how-to-create-a-gem-from-scratch-24f9048ceee1
---

We will walk through the basic steps needed to create a gem and publish it.

![](https://cdn-images-1.medium.com/max/1024/1*70DsXmKuo8nDnXoWAUq01w.jpeg)

## Introduction

> RubyGems has been included with Ruby itself since Ruby 1.9, and is central to Ruby code distribution. It allows Ruby developers to package their code up into a single compressed file, called a "gem". Gems have filenames that end in the .gem extension, and they contain both the Ruby code that makes up the library in question and metadata about the library, including author and version information.
> 
> Hal Fulton.

We will create a gem that will [MonkeyPatch](https://en.wikipedia.org/wiki/Monkey_patch) the [String](https://ruby-doc.org/core-2.6.3/String.html) class in the Ruby language. It will introduce two new methods.

These methods will allow us to modify a string by randomly removing half the characters of it. We will call our gem [thanoscase](https://rubygems.org/gems/thanoscase).

The name of the gem must be unique within the RubyGems ecosystem. So if you want to follow along with the steps for creating the gem, remember to change its name.

The only requirement for you is to have [Ruby 1.9 or greater is in your system](https://github.com/rbenv/rbenv). A little bit of [GitHub](https://medium.com/@nisevi/how-to-create-a-github-repository-3990a467661e) won't hurt either.

## Crafting the gem

The first thing will be to create the structure we need to have a gem published in [RubyGems](https://rubygems.org/). As you can see in the gist below:

{% gist https://gist.github.com/nisevi/5fb26f097828e7e370760a74cdefb9a6 %}

### Basic file structure

We will type a couple of commands in our console:

`mkdir -p thanoscase/lib/thanoscase`

`touch thanoscase/lib/thanoscase/string.rb`

`touch thanoscase/lib/thanoscase.rb`

`touch thanoscase/thanoscase.gemspec`

![](https://cdn-images-1.medium.com/max/800/1*YCcBaUYivv69ipbNOfI0Rw.png)<figcaption>Commands for creation of basic file structure</figcaption>

**string.rb**

It will hold the logic for the methods that are going to be added to the String class. As can be seen here:

{% gist https://gist.github.com/nisevi/6bdf8147f458ca047a55d79453aab086 %}

**thanoscase.gemspec**

> The gemspec defines what’s in the gem, who made it, and the version of the gem. It’s also your interface to [RubyGems.org](http://rubygems.org/). All of the information you see on a gem page (like [jekyll](http://rubygems.org/gems/jekyll)’s) comes from the gemspec.

{% gist https://gist.github.com/nisevi/0b36705a9764e304efa809042cb8f689 %}

**thanoscase.rb**

At this point, we will use thanoscase.rb as a placeholder for importing other libraries. In this case, we are importing the class String.

{% gist https://gist.github.com/nisevi/34a3bc2afb3970f7ace0882df8156271 %}

## Pushing changes to RubyGems

Once all the files are created, we need to build the gem. We will build it from the thanospec.gemspec specifications.

Inside your root folder run the following command:

`gem build thanoscase.gemspec`

![](https://cdn-images-1.medium.com/max/780/1*PZnCMm3_-MA53NYoXiv2bw.png)<figcaption>Command used for building the gem</figcaption>

### Installing and using our newly created gem

Run this for installing the gem locally:

`gem install thanoscase-0.0.1.gem`

![](https://cdn-images-1.medium.com/max/822/1*EaEcGaceHlZiCTAV4XBoIQ.png)<figcaption>Command used for installing</figcaption>

Now we will trigger the irb console and we will play along a little bit with our gem.

![](https://cdn-images-1.medium.com/max/886/1*5XDYxZQsSEhza9u0VgOzuw.png)

irb stands for [interactive ruby](https://ruby-doc.org/stdlib-2.6.3/libdoc/irb/rdoc/IRB.html) is a tool to interactively execute Ruby expressions read from the standard input.

require 'thanoscase' is used for importing our library so we can play with it.

### Pushing our gem to RubyGems

First, you will need to login into RubyGems:

`gem signin`

![](https://cdn-images-1.medium.com/max/806/1*s2BiHKmJdFEeaY4b4B6PqQ.png)<figcaption>Command used for signing into RubyGems</figcaption>

And now what we have been waiting for!! Time to push your gem!!!

`gem push thanoscase-0.0.1.gem`

We are done!! Now your newly created gem can be installed from anywhere!!!

`gem install thanoscase`

Gem creation ends here. If you want to keep reading, we will add tests to our gem and continuous integration for tests to run automatically on every build.

## RSpec for testing

It is a good practice to have tests in place for covering the functionality we have created.

Being said that, we will install [RSpec](https://rspec.info/), a tool for testing.

Add this line to your gemspec file:

`s.add\_development\_dependency "rspec", "~\> 3.8"`

It should look like this:

{% gist https://gist.github.com/nisevi/d443ca3458f14be9f62ae1dea010498a %}

We will need to create a `Gemfile`, inside our root folder:

`touch Gemfile`

Add the following lines to it:

`echo "source 'https://rubygems.org'" \>\> Gemfile`

`echo "gemspec" \>\> Gemfile`

We are all set. Run the bundle command in order to install the RSpec dependency:

`bundle`

![](https://cdn-images-1.medium.com/max/794/1*xe7qJn4UBiuHxxxTpAw0tQ.png)

If you don't have bundler installed, you will need to run:

`gem install bundler`

If you want to install a specific bundler version:

`gem install bundler -v 1.17.3`

[A new file will be created](https://bundler.io/v1.3/rationale.html#sharing-your-application-with-other-developers). Gemfile.lock will keep track of the library versions we are using.

> When your co-developers (or you on another machine) check out your code, it will come with the exact versions of all the third-party code your application used on the machine that you last developed on (in the Gemfile.lock). When \*\*they\*\* run bundle install, bundler will find the Gemfile.lock and skip the dependency resolution step. Instead, it will install all of the same gems that you used on the original machine.

Once RSpec is installed. Run rspec --init to set up your project to use RSpec.

`rspec --init`

A folder spec will be created with a file inside called `spec\_helper.rb`. This file holds the basic and default configuration for RSpec to work. All tests will be expected to be placed under the spec folder.

Following this convention, we proceed to emulate our lib folder structure. We will create a file called `string\_spec.rb` as follows:

`mkdir -p spec/lib/thanoscase`

`touch spec/lib/thanoscase/string.rb`

And our file structure should look something like this:

![](https://cdn-images-1.medium.com/max/680/1*DxxLr7pdA7-kDzx5j4KJ4Q.png)<figcaption>File structure for specs</figcaption>

Inside our `string\_spec.rb` file, we will write a couple of tests:

{% gist https://gist.github.com/nisevi/e549c92acee32713cc5366d0ddae816b %}

Now we can run our test with:

`bundle exec rspec --format documentation`

![](https://cdn-images-1.medium.com/max/1024/1*s7-nJaL8uoGnbFDVArJ7Cg.png)<figcaption>The command for running specs</figcaption>

## CircleCI 2.1 for Continuous Integration

Once you have created a [GitHub](https://medium.com/@nisevi/how-to-create-a-github-repository-3990a467661e) repository and pushed all your changes to the cloud, your code will be able to receive contributions from all around the globe.

In order to ease the way to handle contributions (from other people or your own), we can automate the tests for running every time a new branch is created, or a new commit is pushed to such a branch.

Create a folder called .circleci with a configuration file inside config.yml :

`mkdir .circleci`

`touch .circleci/config.yml`

And inside this configuration file copy the following lines:

{% gist https://gist.github.com/nisevi/c18092e199357515ecbfa336e417d48d %}

Once you have pushed these changes to your GitHub repository. And added the project to CircleCI, your tests will be running every time a contribution is made. You can take a look [here](https://circleci.com/gh/nisevi/thanoscase) for seeing how the specs were run.

## Links of interest

- [RubyGems Guides](https://guides.rubygems.org/);
- [Source code for](https://github.com/nisevi/thanoscase)[thanoscase gem](https://github.com/nisevi/thanoscase);
- [CircleCI Caching Dependencies](https://circleci.com/docs/2.0/caching/);
- [RSpec main site](https://rspec.info/);
- [Using Workflows to Schedule Jobs](https://circleci.com/docs/2.0/workflows/);
- [CircleCI 2.1 Config Overview](https://discuss.circleci.com/t/circleci-2-1-config-overview/26057);
- [The Ruby Way. Third Edition](http://therubyway.io/);

* * *