How to create a Ruby gem

ruby_gemRuby gems are a way of adding functionality to programs written in Ruby, including the popular web application framework Ruby on Rails. Gems are also a way for people to share their code to the world and contribute to open source.

This is a step-by-step guide to show you how to create and publish your own Ruby gem to Rubygems.org.

Create a git repository

You can use any git service like Github, Gitlab, or Bitbucket for this purpose. In this article we will use Github to share our gem.

gem_github

Ignore the README, LICENSE, and .gitignore as we will generate those later.

Clone your repository

git clone [email protected]:yourname/onepunchman.git

This will clone an (almost) empty repository. To build our gem, we will use Bundler’s gem creator command to get a skeleton framework so that we can start quickly. This gem creator also provides useful defaults which make our life easier when creating Ruby gems.

We start by creating a temporary directory where we will place the generated code of Bundler’s gem builder.

mkdir TEMPORARY
cd TEMPORARY
bundle gem onepunchman

It will ask some questions on what additional files to include:

Do you want to include a code of conduct in gems you generate?
Codes of conduct can increase contributions to your project by contributors who prefer collaborative, safe spaces. You can read more about the code of conduct at contributor-covenant.org. Having a code of conduct means agreeing to the responsibility of enforcing it, so be sure that you are prepared to do that. For suggestions about how to enforce codes of conduct, see bit.ly/coc-enforcement. y/(n): y
Code of conduct enabled in config

Do you want to license your code permissively under the MIT license?
This means that any other developer or company will be legally allowed to use your code for free as long as they admit you created it. You can read more about the MIT license at choosealicense.com/licenses/mit. y/(n): y
MIT License enabled in config

Do you want to generate tests with your gem?
Type 'rspec' or 'minitest' to generate those test files now and in the future. rspec/minitest/(none): minitest

It is recommended that you include the Code of Conduct declaration, and set the license to MIT License so that others can freely use your code for any purpose. When deciding on the test framework, RSpec is fine but Minitest is the more lightweight option and still does the job.

The previous command will generate the following files:

create onepunchman/Gemfile
create onepunchman/.gitignore
create onepunchman/lib/onepunchman.rb
create onepunchman/lib/onepunchman/version.rb
create onepunchman/onepunchman.gemspec
create onepunchman/Rakefile
create onepunchman/README.md
create onepunchman/bin/console
create onepunchman/bin/setup
create onepunchman/CODE_OF_CONDUCT.md
create onepunchman/LICENSE.txt
create onepunchman/.travis.yml
create onepunchman/test/test_helper.rb
create onepunchman/test/onepunchman_test.rb

The main file is located at lib/onepunchman.rb. This file sets up the entire gem and is the one that is included when you run “require ‘onepunchman'”.

Copy all the files under TEMPORARY/onepunchman into the “onepunchman” directory you cloned from github. Make sure you do not include the .git hidden folder.

Update the gemspec

The gemspec defines the details of the gem such as author information, description, dependencies, etc. Update this file to put in the gem’s description, which will be shown publicly once we push this to Rubygems.org.

Gem::Specification.new do |spec|
spec.name = "onepunchman"
spec.version = Onepunchman::VERSION
spec.authors = ["Juan dela Cruz"]
spec.email = ["[email protected]"]

spec.summary = %q{Destroy all bugs with one punch!}
spec.description = %q{This gem fixes all the bugs in your application using a single command.}
spec.homepage = "https://rubygems.org/gems/onepunchman"
spec.license = "MIT"

...(other details here)...
end

Build your gem

You can now try to build or package your gem (without any functionality).

gem build onepunchman.gemspec

WARNING: open-ended dependency on minitest (>= 0, development) is not recommended
if minitest is semantically versioned, use:
add_development_dependency 'minitest', '~> 0'
WARNING: See http://guides.rubygems.org/specification-reference/ for help

When this error message appears, edit the gemspec file to set the minimum versions for all your dependencies.

spec.add_development_dependency "bundler", "~> 1.10"
spec.add_development_dependency "rake", "~> 10.0"
spec.add_development_dependency "minitest", '~> 5'

The build command will create onepunchman-0.1.0.gem. You have now created your own gem, but at the moment it doesn’t do anything.

Add your functionality

Your newly-created gem does not do anything at this point. To add functionality to your gem, we will need to add code in Ruby classes. In this example we will add the code to perform “attacks”.

Add lib/onepunchman/attack.rb

class Onepunchman::Attack
def initialize
end

def normal_punch
print "Normal punch!"
return "boom!"
end

def serious_punch
print "Serious punch!"
return "BOOM!"
end

end

Require the file in lib/onepunchman.rb

require "onepunchman/version"
require "onepunchman/attack"

module Onepunchman
# Your code goes here...
end

Run your gem

Now that you have included something that your gem will do, you can now test it out by running your gem and trying out the “attacks”. First we will need to install the dependencies that our gem needs using the following command:

./bin/setup

This runs bundle install and installs the dependencies of your gem. We can now then install the gem using the usual way, but we specify the actual packaged gem file instead of fetching it via the internet.

gem install onepunchman-0.1.0.gem

To test it out, we can open an IRB (Interactive Ruby) instance and require our gem.

irb
irb> require 'onepunchman'

Alternatively, we can also use the console command that is built in when we used Bundler’s gem creator.

./bin/console

This commands runs an IRB instance where your gem is automatically loaded.

> attack = Onepunchman::Attack.new
=> #
> attack.normal_punch
Normal punch! > "boom!"
> attack.serious_punch
Serious punch! > "BOOM!"

Write tests

It is important that you write tests for your gem. It serves two purposes: it maintains the quality of your code so you do not publish broken functionality, and it also serves as documentation on how your gem works.

When you look at the test folder, you will see two files:

  • test_helper.rb
  • onepunchman_test.rb

The test_helper.rb file loads your gem and the Minitest gem when you run tests. You do not need to modify this file unless you need additional configuration for your tests.

The sample tests in the onepunchman_test.rb already provide a test that checks whether you have a version specified or not:

require 'test_helper'

class OnepunchmanTest < Minitest::Test
  def test_that_it_has_a_version_number
    refute_nil ::Psei::VERSION
  end

  def test_it_does_something_useful
    assert false
  end
end

We will need to update the second test so that it actually tests the functionality. For instructions on how to create Minitest specs, please refer to the README.

In this example we will need to test that the normal punch and serious punch attacks return the correct response.

You can create Unit tests or Specs using Minitest:

require 'test_helper'
# An example using unit tests
class OnepunchmanTest < Minitest::Test
  def setup
    @saitama = Onepunchman::Attack.new
  end
  
  def test_that_it_has_a_version_number
    refute_nil ::Onepunchman::VERSION
  end

  def test_normal_punch
    assert_equal "boom!", @saitama.normal_punch
  end
end
require 'test_helper'
# An example using specs
describe Onepunchman do
  before do
    @saitama = Onepunchman::Attack.new
  end

  describe "when using a normal attack" do
    it "must respond strongly" do
      @saitama.normal_punch.must_equal "boom!"
    end
  end

  describe "when using a serious attack" do
    it "must respond VERY strongly" do
      @saitama.serious_punch.must_equal "BOOM!"
    end
  end
end

Run your tests using this command:

rake test

If all of your tests pass, it will show an output similar to this:

Run options: --seed 63377

# Running:

.Normal punch!.Normal punch!.Serious punch!.

Finished in 0.003868s, 1034.2599 runs/s, 1034.2599 assertions/s.

4 runs, 4 assertions, 0 failures, 0 errors, 0 skips

Publish your gem to RubyGems.org

Once we have added the functionality and the corresponding tests to our gem, we can now publish it to the world via Rubygems.org. You will need to provide your account details in order to push your gem.

$ gem push onepunchman-0.1.0.gem
Enter your RubyGems.org credentials.
Don't have an account yet? Create one at https://rubygems.org/sign_up
Email: gem_author@example
Password:
Signed in.
Pushing gem to RubyGems.org...
Successfully registered gem: onepunchman (0.1.0)

Your gem is now published to Rubygems.org and you can view your gem using this URL:

https://rubygems.org/gems/onepunchman

Now on your Ruby or Rails code you can now install your published gem!

gem install onepunchman

Releasing new versions

During your gem's lifetime you will need to release a new version when you improve or change the functionality. To do this, update the version in lib/onepunchman/version.rb

module Onepunchman
VERSION = "0.2.0"
end

Then push your changes and mark your release:

$ git add
$ git commit -m "Release for 0.2.0"
$ git push
$ git tag -a v0.2.0 -m "Add new attacks"
$ git push --tags

Build the new version of your gem:

$ gem build onepunchman.gemspec

This will generate onepunchman-0.2.0.gem

Then publish the new version of your gem to Rubygems.org:

$ gem push onepunchman-0.2.0.gem

Leave a Reply

Your email address will not be published. Required fields are marked *