Guides

Getting Started

Guides

Dependency Management

Gem Development

Publishing & Security

Integrations

Hosting & Sources

Extending

Troubleshooting

Concepts

Reference

Appendix

Patterns

Common practices to make your gem users’ and other developers’ lives easier.

This page covers conventions for naming and structuring a gem and for loading its code. Guidance that used to live here has moved: for version numbering, prerelease versions, and dependency constraints see Versioning and compatibility, and for where to declare runtime and development dependencies see Gemfile and gemspec.

Consistent naming

There are only two hard things in Computer Science: cache invalidation and naming things. -Phil Karlton

File names

Be consistent with how the files of your gem are named. This is the layout bundle gem hola --exe generates, with the support files trimmed:

% tree hola
hola
├── Gemfile
├── Rakefile
├── exe
│   └── hola
├── hola.gemspec
├── lib
│   ├── hola
│   │   └── version.rb
│   └── hola.rb
└── test
    ├── test_helper.rb
    └── test_hola.rb

The executable in exe and the primary file in lib are named after the gem. A developer can easily jump in and call require 'hola' with no problems. Everything beyond the primary file lives in a directory with the gem’s name, like lib/hola/version.rb, for reasons covered in the Loading code section below.

Naming your gem

Naming your gem is important. Before you pick a name for your gem, do a quick search on RubyGems.org and GitHub to see if someone else has taken it. Every published gem must have a unique name. Be sure to read our naming recommendations when you’ve found a name you like.

Loading code

At its core, RubyGems exists to help you manage Ruby’s $LOAD_PATH, which is how the require statement picks up new code. There’s several things you can do to make sure you’re loading code the right way.

Respect the global load path

When packaging your gem files, you need to be careful of what is in your lib directory. Every gem you have installed gets its lib directory appended onto your $LOAD_PATH. This means any file on the top level of the lib directory could get required.

For example, let’s say we have a foo gem with the following structure:

.
└── lib
    ├── foo
    │   └── cgi.rb
    ├── erb.rb
    ├── foo.rb
    └── set.rb

This might seem harmless since your custom erb and set files are within your gem. However, this is not harmless, anyone who requires this gem will not be able to bring in the ERB or Set classes provided by Ruby’s standard library.

The best way to get around this is to keep files in a different directory under lib. The usual convention is to be consistent and put them in the same folder name as your gem’s name, for example lib/foo/cgi.rb.

Requiring files relative to each other

Gems should not have to use __FILE__ to bring in other Ruby files in your gem. Code like this is surprisingly common in gems:

require File.join(
          File.dirname(__FILE__),
          "foo", "bar")

Or:

require File.expand_path(File.join(
          File.dirname(__FILE__),
          "foo", "bar"))

The fix is simple, just require the file relative to the load path:

require 'foo/bar'

Or use require_relative:

require_relative 'foo/bar'

The make your own gem guide has a great example of this behavior in practice, including a working test suite. The code for that gem is on GitHub as well.

Mangling the load path

Gems should not change the $LOAD_PATH variable. RubyGems manages this for you. Code like this should not be necessary:

lp = File.expand_path(File.dirname(__FILE__))
unless $LOAD_PATH.include?(lp)
  $LOAD_PATH.unshift(lp)
end

Or:

__DIR__ = File.dirname(__FILE__)

$LOAD_PATH.unshift __DIR__ unless
  $LOAD_PATH.include?(__DIR__) ||
  $LOAD_PATH.include?(File.expand_path(__DIR__))

When RubyGems activates a gem, it adds your package’s lib folder to the $LOAD_PATH ready to be required normally by another lib or application. It is safe to assume you can then require any file in your lib folder.

Don’t use gem from within your gem

You may have seen some code like this around to make sure a specific version of a gem is activated before requiring it:

gem "extlib", ">= 1.0.8"
require "extlib"

Gems should not do this. Declare the requirement in the gemspec instead, so the resolver can weigh it together with every other gem’s requirements, and let RubyGems handle activating the right version. Applications control their dependency versions with Bundler rather than gem calls.

Credits

Several sources were used for content for this guide: