RubyGems

A comprehensive guide to finding, creating and using Ruby resources called gems.
Developers

Now that you have some software installed, you will want to use it. To get started, you may want to read the documentation on the gems to learn their API. If you have installed rdoc on your system, gem automatically generates the rdoc (Ruby documentation) for all of the gems you install. You can view this documentation in two different ways. The first one is to run the command:

gem_server

This automatically launches a Ruby-based Web server on port 8808. You can add the -p option to launch the server on a different port. This makes it easy for you to use your Web browser to browse the documentation for all of the gems that are installed. The gem_server can be stopped by pressing Ctrl-C. Also, be aware that the server accepts connections from all hosts that are able to connect to that port. So, if you are concerned about opening a port on your server, you may want to try the alternate means of access.

The other way to access this documentation is to navigate to the place on the filesystem where gem has generated it. In most cases, it will be in /usr/lib/ruby/gems/1.8/doc, but in the event that gem has been installed in a different path, you can ask gem where the correct directory is:

gem environment gemdir

This command gives you the base directory where gem is installed. The documentation is stored in the doc subdirectory of that directory. When you access the files this way, you do not get the summary overview that you get from the gem_server; instead you get only a directory listing of all the gems that are installed.

In order to make your Ruby scripts able to use the Ruby libraries you have now installed, you need to use Ruby's require mechanism to load in the code. The simplest way to use RubyGems is to call the following lines:

require 'rubygems'
require 'RMagick'

This loads all the RubyGems code and automatically allows you to use the latest gem version of RMagick that you have installed. If the code is available locally, it will be included from there instead.

If you would like to tie your software to a specific version of the library, a different function must be called:


require 'rubygems'
require_gem 'RMagick' , '>=1.10'
require_gem 'rake', '>=0.7.0', '<0.9.0'

These statements tell Ruby to use RMagick as long as it is greater than or equal to 1.10. The second line allows any version of rake as long as it is greater than or equal to 0.7 and less than 0.9.0. The version statement supports a number of operators: =, !=, >, >=, <, <= and ~>. The last one is a special operator. It assumes that you are following a RubyGems standard for versioning.

X.Y.Z

You increase X when you release a version that is incompatible with the previous version. You increase Y when you release a version with a new feature that is otherwise compatible. You increase Z when you release a fix for the software.

This allows the ~> requirement to select within a special range. So for example: 1.0, 1.0.1, 1.0.2,1.1 are all ~> 1.0, and 1.1, 1.1.2 are ~> 1.1.

This lets you support minor changes in the gem version without having to change the require statements in your code.

A word of advice: if you are putting in require statements that are tied to a version, make sure you have a central place for calling and organizing them. This will make it easier to determine what other software you depend on and to adjust version requirements later when they need to change.

Building Your Own

So far, gems have really been about using other people's software in your code. If you decide you have a library that might be useful to other people, you easily can package it up as a gem.

Now that you know how to use gems, you might want to know how to build them. The process of turning your code into a gem is a two-part process. The nice thing about that process is you do not have to modify your code to make it available as a gem. The first part is getting your library set up in a directory structure that is suitable for conversion to a gem. I'm going to be using an existing project called IPAdmin (see Resources) as my example of how this works.

The directory structure is organized as follows:

  • /ipadmin/lib: this directory contains all of the Ruby code related to the project.

  • /ipadmin/pkg: this is where the gem will be generated.

  • /ipadmin/tests: this is where any unit or other tests should be stored.

  • /ipadmin/README: this file should contain a summary of the project—especially the license under which it is being released (feel free to add a separate file for the license).

This is the bare minimum layout you need to build up a gem.

More complex projects (rake for example) add the following directories:

  • /rake/bin: this is for any command-line scripts that are part of the project.

  • /rake/doc: additional documentation about the project.

This shows how some projects (rake, capistrano) are able to add in new command-line tools once they are installed on a system.

RMagick includes a special directory:

  • /RMagick/ext: this is where non-Ruby source should be stored if it is going to be compiled.

This is another power option. RubyGems supports shipping non-Ruby source code in the gem. When the user installs this “source” gem on the destination computer, gem attempts to compile the extra code as part of the installation. The advantage of shipping a gem this way is that the non-Ruby code will bind to the actual libraries that are installed on the destination computer. This is exactly what happens when you install RMagick. If you do not have the proper libraries (ImageMagick) or a compiler, the install will fail. To get around the problem of not being able to compile the code, it is possible to ship a precompiled version of the gem. In this case, the source files are compiled and then simply included in the gem.

Once you have your code set up in the correct directory structure, you can focus on the other part of the process of gem building—the gem specification. This is basically a manifest that gives gem all the information it needs about the gem being built. You can build a gem spec as a standalone file, but it is easier to work with if you make it a Rakefile. This simplifies the building process.

There is a Rakefile in the main directory of IPAdmin:

require 'rubygems'
Gem::manage_gems
require 'rake/gempackagetask'

spec = Gem::Specification.new do |s|
    s.platform  =   Gem::Platform::RUBY
    s.name      =   "ipadmin"
    s.version   =   "0.2.2"
    s.author    =   "Dustin Spinhirne"
    s.email     =   "dspinhir @nospam@ yahoo.com"
    s.summary   =   "A package for manipulating IPv4/IPv6 address space."
    s.files     =   FileList['lib/*.rb', 'test/*'].to_a
    s.require_path  =   "lib"
    s.autorequire   =   "ip_admin"
    s.test_files = Dir.glob('tests/*.rb')
    s.has_rdoc  =   true
    s.extra_rdoc_files  =   ["README"]
end

Rake::GemPackageTask.new(spec) do |pkg|
    pkg.need_tar = true
end

task :default => "pkg/#{spec.name}-#{spec.version}.gem" do
    puts "generated latest version"
end

This is a good example of a standard Rakefile for a gem. Here you can see that it is including RubyGems and adding some tasks from rake. The main spec handles providing all the information about the gem that is being built. The last task adds a simple helper that allows you to run rake in the directory and automatically build a gem.

Each of the lines in the spec has a special meaning. The entire list of options that can be set is available from the Gemspec Reference on the RubyGems Manuals site (see Resources).

______________________

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

the option --include-dependencies is the default

Jian Lin's picture

gem install rails --include-dependencies

can be

gem install rails

the

--include-dependencies

is now the default on the current gem 1.3.7

Coco

Anonymous's picture

Thank you for this article, posted on May 27, 2006 and still helping people!;)

nice stuff

Kanuverleih's picture

Thank You for another very interesting article.
It’s really good written and I fully agree with You
on main issue, btw. I must say that I really enjoyed
reading all of Your posts. It’s interesting to read ideas,
and observations from someone else’s point of view… it makes
you think more. So please try to keep up the great work all the time.

Webinar
One Click, Universal Protection: Implementing Centralized Security Policies on Linux Systems

As Linux continues to play an ever increasing role in corporate data centers and institutions, ensuring the integrity and protection of these systems must be a priority. With 60% of the world's websites and an increasing share of organization's mission-critical workloads running on Linux, failing to stop malware and other advanced threats on Linux can increasingly impact an organization's reputation and bottom line.

Learn More

Sponsored by Bit9

Webinar
Linux Backup and Recovery Webinar

Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.

In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.

Learn More

Sponsored by Storix