This is a tiny guide to creating a new ruby gem. Gems in ruby are reusable libraries, components, packages, and/or applications. Consider writing gems as opposed to putting everything into a single application. (You can combine gems into a single application, but it makes sense to have separate components that do one thing really well.)

Documentation

The rubygems documentation describe how to do all this in fairly good detail, and they are the benchmark for creating accurate gems. Read through the guides to learn what things are and how to use, create, and manage gems.

Getting started

In this article, I’ll be giving a walk-through of my typical workflow in creating a gem.

Using bundler to create a new gem

For my needs, bundler does the initial heavy-lifting to put a basic gem scaffolding in place:

$ bundle gem my_gem --test
      create  my_gem/Gemfile
      create  my_gem/Rakefile
      create  my_gem/LICENSE.txt
      create  my_gem/README.md
      create  my_gem/.gitignore
      create  my_gem/my_gem.gemspec
      create  my_gem/lib/my_gem.rb
      create  my_gem/lib/my_gem/version.rb
      create  my_gem/.rspec
      create  my_gem/spec/spec_helper.rb
      create  my_gem/spec/my_gem_spec.rb
      create  my_gem/.travis.yml
Initializating git repo in /Users/tamara/Documents/tamouse.github.io/source/downloads/code/2013-11-29-developing-a-ruby-gem/my_gem

First thing after this is hop into the new gem’s directory, and modify the .gemspec file:

$ git diff my_gem.gemspec 
diff --git a/my_gem.gemspec b/my_gem.gemspec
index 62ca81d..2cd4451 100644
--- a/my_gem.gemspec
+++ b/my_gem.gemspec
@@ -8,9 +8,9 @@ Gem::Specification.new do |spec|
   spec.email         = ["tamouse@gmail.com"]
-  spec.description   = %q{TODO: Write a gem description}
-  spec.summary       = %q{TODO: Write a gem summary}
-  spec.homepage      = ""
+  spec.description   = %q{my gem description}
+  spec.summary       = %q{my gem summary}
+  spec.homepage      = "http://github.com/tamouse/my_gem"
   spec.license       = "MIT"

This is a good start, but there are more things I like to add.

Guard – for continuous testing

The [Guard gem][guard] provides a means of continuous testing by watching various directories in your gem’s tree and performing specific actions based on modifications in files. Since [RSpec][rspec] is my testing tool of choice for Ruby, I include the following in the newly-created .gemspec file:

@@ -21,4 +21,8 @@ Gem::Specification.new do |spec|
   spec.add_development_dependency "bundler", "~> 1.3"
   spec.add_development_dependency "rake"
   spec.add_development_dependency "rspec"
+
+  spec.add_development_dependency "guard"
+  spec.add_development_dependency "guard-bundler"
+  spec.add_development_dependency "guard-rspec"
 end

There are lots of guards available, visit the [Guard Organization][guard-org] to see what’s there.

Once that’s saved, initialize guard:

$ bundle exec guard init
16:13:24 - INFO - Writing new Guardfile to /Users/tamara/Documents/tamouse.github.io/source/downloads/code/2013-11-29-developing-a-ruby-gem/my_gem/Guardfile
16:13:24 - INFO - bundler guard added to Guardfile, feel free to edit it
16:13:24 - INFO - rspec guard added to Guardfile, feel free to edit it

Since we’ve included Guard in the .gemspec file, we need to run it with bundle exec. An alternative is to leave the Guard stuff out of the .gemspec and use global settings. I prefer to include it.

I always edit the resulting Guardfile, making the following changes:

$ git diff
diff --git a/Guardfile b/Guardfile
index 6b1588c..0e69679 100644
--- a/Guardfile
+++ b/Guardfile
@@ -1,30 +1,11 @@
-# A sample Guardfile
-# More info at https://github.com/guard/guard#readme
-
 guard :bundler do
   watch('Gemfile')
-  # Uncomment next line if your Gemfile contains the `gemspec' command.
-  # watch(/^.+\.gemspec/)
+  watch(/^.+\.gemspec/)
 end
 
 guard :rspec do
   watch(%r{^spec/.+_spec\.rb$})
   watch(%r{^lib/(.+)\.rb$})     { |m| "spec/lib/#{m[1]}_spec.rb" }
   watch('spec/spec_helper.rb')  { "spec" }
-
-  # Rails example
-  watch(%r{^app/(.+)\.rb$})                           { |m| "spec/#{m[1]}_spec.rb" }
-  watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$})          { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
-  watch(%r{^app/controllers/(.+)_(controller)\.rb$})  { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}
-  watch(%r{^spec/support/(.+)\.rb$})                  { "spec" }
-  watch('config/routes.rb')                           { "spec/routing" }
-  watch('app/controllers/application_controller.rb')  { "spec/controllers" }
-
-  # Capybara features specs
-  watch(%r{^app/views/(.+)/.*\.(erb|haml|slim)$})     { |m| "spec/features/#{m[1]}_spec.rb" }
-
-  # Turnip features and steps
-  watch(%r{^spec/acceptance/(.+)\.feature$})
-  watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$})   { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
 end

Initialize RSpec

When using the -t option on bundle gem, a spec folder is automatically created, containing a dummy spec test and the RSpec helper file, spec_helper.rb. An .rspec rc file is also included.

The dummy spec can be used as a template for other spec files. The spec directory structure should be a mirror analog of the lib directory, including the lib directory itself:

$ mkdir -p spec/lib/my_gem
$ tree
   |-lib
   |---my_gem
   |-spec
   |---lib
   |-----my_gem