Create a Gem - Make it a Command Line Interface - Add Rspec Tests Using Bundler & Thor
#Creating your own Gem
-
Run this command in your Terminal. This creates and names all the files you need for your gem. We are going to create a Lorem Ipsum Generator; you can call it whatever you want but seeing as we are creating a Lorem Ipsum generator we'll call it lorem. Read about gem naming conventions.
$ bundle gem lorem
Notice that this command also initialized a git repository for you on your local machine and gives you the path name for it.
-
cd into lorem. Use
$ ls
to list your files that were just generated.Gemfile Rakefile LICENSE.txt README.md .gitignore lorem.gemspec lib/lorem.rb lib/lorem/version.rb
-
Make your
lorem.gemspec
file look like this. Add your name and your email.
"In order to create a gem, you need to define a gem specification, commonly called a
gemspec.
A gemspec consists of several attributes. Some of these are required; most of them are optional. The main body of this document is an alphabetical list of gemspec attributes, each with a description, example usage, notes, and more." Read more about the gemspec file.
\# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'lorem/version'
Gem::Specification.new do |spec|
spec.name = "lorem"
spec.version = Lorem::VERSION
spec.platform = Gem::Platform::RUBY
spec.authors = ["your name"]
spec.email = ["[email protected]"]
spec.homepage = ""
spec.summary = %q{Jenipsum generator}
spec.description = %q{Generates jenipsum text}
spec.license = "MIT"
spec.add_development_dependency "bundler", "~> 1.3"
spec.add_development_dependency "rake"
spec.files = `git ls-files`.split($/)
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
end
If you neglect to change these areas you will get this error when you go to run $ gem build lipsum.gemspec
ERROR: While executing gem ... (Gem::InvalidSpecificationException)
"FIXME" or "TODO" is not a description
-
Open your file
lib/lorem.rb
Make it look like this. This is the file that is loaded when people require your gem. You can customize it with the behavior you want it to have.require "lorem/version" module Lorem def self.ipsum "Fantastic, yes, but gory. Help. It is a juniper. Pikku and Friendly ate all the kibbles. Formaldehyde, an exacto, a comb, a napkin, and a typewriter combined with vitamins, a bicycle, whiskey, batteries, flippers and a bike messenger twisted around the bend one curve at a time during the entire tour through Texas with Madi and my bass. Veragogo had a plan for fame and flicker of flash bulbs but all the costumes turned into jerseys and centuries with views of flowers, yucca, jelly, blueberries and guava paste. My teeth broke in an accident with the turbo trainwreck I call myself in my twenties. Floppy hair, green eyes and a slick bike are the formula in geometry for a Pickaxe turned Park n' Ride. The stripped cats, Lars, pompoms, sneakers, bubbler and litter boxes all make California seem like home, Massachusetts. Finland is stress-free where you can relax, swim and bike. Do a triathlon in Palm Springs or Oxnard in November or early October while listening to Vanity Press and Go Away Evil. Dudley is a great place to visit in the winter at Christmas." end end
-
Run this command.
$ gem build lorem.gemspec
Here are some good resources if you have questions.
Video tutorial that will explain all the files and file structure.
This is Bundler's Tutorial
RubyGems Guides
Our example gem is called lorem. Replace lorem with your gem directory name accordingly.
-
Go into your Gem directory
$ cd lorem
-
Create a cli.rb file in
lib/lorem
In this file create a class that inherits from Thor and your lorem file. Add all of this code.require "thor" require "lorem" module Lorem class CLI < Thor desc "ipsum", "Lorem Ipsum text generator" def ipsum puts Lorem.ipsum end end end
Read more about this on the Thor website http://whatisthor.com/
-
Create bin folder
$ mkdir bin
-
Create executable file naming it what you want your gem command to be. Do not add a .extention to it. Add the following code into your
bin/lorem
file#!/usr/bin/env ruby require "lorem/cli" Lorem::CLI.start
-
In lorem.gemspec, add this before
end
spec.add_runtime_dependency "thor"
There are 2 possible ways to run it.
-
$ ruby -I lib bin/lorem ipsum
-
$ bundle exec bin/lorem ipsum
If you get an
$ ERROR bundler: not executable: bin/gem_command_name
Run
$ chmod +x bin/gem_command_name
Once it is installed locally you can run your gem in your command line by it's name. $ lorem
gem install --local lorem
gem push zipper-0.0.1.gem
Add this line to your application's Gemfile:
gem 'lorem'
And then execute:
$ bundle
Or install it yourself as:
$ gem install lorem
We are trying to test that Lorem Ipsum is actually generated. This creates a spec Directory and a spec_helper.rb
-
Run this in your command line.
$ rspec --init
Checkout the files that were just generated.
$ ls Gemfile lib L lorem.rb L lorem L version.rb LICENSE.txt lorem.gemspec Rakefile README.md spec L spec_helper.rb
-
In the lorem.gemspec file, add
spec.add_development_dependency "rspec"
beforeend
\# coding: utf-8 lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'lorem/version' Gem::Specification.new do |spec| spec.name = "lorem" spec.version = Lorem::VERSION spec.platform = Gem::Platform::RUBY spec.authors = ["your name"] spec.email = ["[email protected]"] spec.homepage = "" spec.summary = %q{Jenipsum generator} spec.description = %q{Generates jenipsum text} spec.license = "MIT" spec.add_development_dependency "bundler", "~> 1.3" spec.add_development_dependency "rake" spec.add_runtime_dependency "thor" spec.add_development_dependency "rspec" spec.files = `git ls-files`.split($/) spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } spec.require_paths = ["lib"] end
-
Create a
lorem_spec.rb
file in your spec directory. This is where you will write your test.$ touch spec/lorem_spec.rb
-
Write this into your spec/lorem_spec.rb
require 'spec_helper' module Lorem describe Lorem do it "should not be empty" do expect(Lorem.ipsum).to_not be_empty end it "should include 'Fantastic'" do expect(Lorem.ipsum).to include('Fantastic') end end end
-
Require your lorem gem in your spec/spec_helper.rb
require "lorem" # This file was generated by the `rspec --init` command. Conventionally, all # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. # Require this file using `require "spec_helper"` to ensure that it is only # loaded once. # # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration RSpec.configure do |config| config.treat_symbols_as_metadata_keys_with_true_values = true config.run_all_when_everything_filtered = true config.filter_run :focus # Run specs in random order to surface order dependencies. If you find an # order dependency and want to debug it, you can fix the order by providing # the seed, which is printed after each run. # --seed 1234 config.order = 'random' end
-
It is now time to run your test.
$ rspec spec/lorem_spec.rb
You should see two passing tests written in green. If instead you see red failures read your errors and keep fixing your code until both tests pass.
Try adding flags and your own Lorem Ipsum. Install it. Publish it. Have fun with your new gem.
I realize this is ancient but it got me off the ground!