Notes On Making a Gem


I decided to make a gem for a bit of practice. I did some googling, and I found a good RailsCast on it.

He uses bundler, which takes care of a lot of the heavy lifting. All I did was run

bundle gem states

This will create a directory with the same name as whatever you called the gem. Then to add RSpec, cd to the directory that was created. Then run

rspec --init

I wanted to make a gem with a few layers in the directory tree. Java package names tend to have multiple levels, while most Ruby gems seem to only go one level deep. Perhaps I will never write a gem that has too many levels, but I wanted to make one with a few levels anyway.

I decided to start with a state in the first level. I added

require "states/hawaii"

to lib/states.rb
Then add a file: lib/states/hawaii.rb

module States
  class Hawaii
    def initialize
      puts "in hawaii"
    end
  end
end

Then I added a test file. Then in spec/spec_helper.rb, add

require 'states'

I added the  file spec/states/hawaii_spec.rb

require "spec_helper"
module States
  describe Hawaii do
    it "should do something" do
      hawaii = Hawaii.new
    end

  end
end

There is another way to recognize the module levels in the RSpec file:

require "spec_helper"

describe States::Hawaii do
  it "should do something" do
    hawaii = States::Hawaii.new
  end

end

I put

require 'spec_helper'

in each spec file.

I also added a class lib/states/illinois.rb, and a test file in spec/states/illinois_spec.rb.

I then tried to add a few classes for Champaign County and Urbana. I tried to put them in a directory lib/states/illinois and in spec/states/illinois.

I got this error:

  lib/states/illinois/champaign_county.rb:2:in `<module:States>': Illinois is not a module (TypeError)

But I changed the directory name to illini, and I updated the files accordingly, and it worked. I changed it all back to “Illinois”, and it stopped working again. So now the module is back to “Illini”. I do not know if Ruby or RSpec will not allow a directory and a class to have the same name, or if I just needed to put illinois.rb in a higher directory. There is a states.rb and a states directory. Perhaps the gem name is an exception to the uniqueness rule. But in the future I will stick with using different names.

So, to summarize, I ran

bundle gem states

Then to add RSpec, I ran

rspec --init

For every class that I made, I put a file in lib, a corresponding file in spec, and I put a require statement in the states.rb file.
And the class file names must not be the same as the directory names.

ericm:/states$ tree
.
├── Gemfile
├── lib
│   ├── states
│   │   ├── hawaii.rb
│   │   ├── illini
│   │   │   ├── champaign
│   │   │   │   └── urbana.rb
│   │   │   └── champaign_county.rb
│   │   ├── illinois.rb
│   │   └── version.rb
│   └── states.rb
├── LICENSE
├── notes.txt
├── Rakefile
├── README.md
├── spec
│   ├── spec_helper.rb
│   └── states
│       ├── hawaii_spec.rb
│       ├── illini
│       │   ├── champaign
│       │   │   └── urbana_spec.rb
│       │   └── champaign_county_spec.rb
│       └── illinois_spec.rb
└── states.gemspec

8 directories, 17 files


I am sure that for a lot of Ruby people, this post will be review. I tried making a gem using some of the code from the RSpec book as a basis, and I could not get it to work. I did the guy thing by trying something without reading the directions. I am thinking of proposing a talk for Lone Star Ruby Conf, and I need to be able to get a gem to work.