Pages

Monday, 16 November 2015

Build gem from Scratch

$ bundle gem lorem
      create  lorem/Gemfile
      create  lorem/Rakefile
      create  lorem/.gitignore
      create  lorem/lorem.gemspec
      create  lorem/lib/lorem.rb
      create  lorem/lib/lorem/version.rb

Initializating git repo in /Users/eifion/code/ep245/lorem

The bundle gem command creates a new directory and generates several files in it. It also initializes a git repository there. This assumes that you’re using git and we’ll explain why it does this shortly. Before we do that we’ll walk you through some of the generated files, starting with the lorem.gemspec file.

/lorem/lorem.gemspec

# -*- encoding: utf-8 -*-
$:.push File.expand_path("../lib", __FILE__)
require "lorem/version"
 
Gem::Specification.new do |s|
  s.name        = "lorem"
  s.version     = Lorem::VERSION
  s.platform    = Gem::Platform::RUBY
  s.authors     = ["TODO: Write your name"]
  s.email       = ["TODO: Write your email address"]
  s.homepage    = ""
  s.summary     = %q{TODO: Write a gem summary}
  s.description = %q{TODO: Write a gem description}
 
  s.rubyforge_project = "lorem"
 
  s.files         = `git ls-files`.split("\n")
  s.test_files    = `git ls-files -- ↵
    {test,spec,features}/*`.split("\n")
  s.executables   = `git ls-files -- bin/*`.split("\n").map{ ↵
    |f| File.basename(f) }
  s.require_paths = ["lib"]
end

We can see straight away by looking at the TODO items that this file is designed to be edited directly. Once we complete these items we’ll have a working Gemspec file. One interesting part of this file are the file attributes towards the end of the file. Each of these is determined at runtime by using the git ls-files command by using git to determine the files that will be included in the gem and this is why bundle gem creates a git repository. The good thing about this is that it will automatically inherit the behaviour of the .gitignore file so that temporary files and the files we don’t want in our git repository (and therefore don’t want in our gem) are excluded. The defaults above will work for most gems but they can always be edited if we need different behaviour.

Another thing to note is how the version number is determined. This is defined as a constant called Lorem::VERSION and this value is defined in another file called version.rb in the lib/lorem directory. All this file does is define the version number.

/lib/lorem/version.rb
module Lorem
  VERSION = "0.0.1"
end
When it’s time to update our gem to a new version we can change the version number here and republish the gem.

The other file generated in the lib directory is called lorem.rb and it’s this file that’s loaded when someone requires our gem. We can put any code we like in this file or create other files in the lib directory and require them here. For our simple Lorem gem we’ll just create a class method called ipsum that returns some Lorem Ipsum text.

/lib/lorem.rb
module Lorem
  def self.ipsum
    "Lorem ipsum dolor sit amet, consectetur adipisicing ...."
  end
end
Publishing

So, we’ve finished our gem now and we’re ready to publish the first version. Before we do we’ll update the Gemspec file and replace the TODO text.

/lorem.gemspec
# -*- encoding: utf-8 -*-
$:.push File.expand_path("../lib", __FILE__)
require "lorem/version"
 
Gem::Specification.new do |s|
  s.name        = "lorem"
  s.version     = Lorem::VERSION
  s.platform    = Gem::Platform::RUBY
  s.authors     = ["Eifion Bedford"]
  s.email       = ["eifion@asciicasts.com"]
  s.homepage    = ""
  s.summary     = %q{Lorem ipsum generator}
  s.description = %q{Simply generates lorem ipsum text.}
 
  s.rubyforge_project = "lorem"
 
  s.files         = `git ls-files`.split("\n")
  s.test_files    = `git ls-files -- {test,spec,features}/*`.split("\n")
  s.executables   = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
  s.require_paths = ["lib"]
end
Then we can run the gem build command and point it to our Gemspec file.

$ gem build lorem.gemspec
WARNING:  no homepage specified
  Successfully built RubyGem
  Name: lorem
  Version: 0.0.1
  File: lorem-0.0.1.gem
This command generates a .gem file. If we were to run the gem push command now that would push the gem up to RubyGems.org and publish it so that others could install it.