1. What is a gem
1.1 Introduction
At its most basic form, a Ruby gem is a package. It contains the necessary files and information for being installed on the system. Quoting RubyGems, «a gem is a packaged Ruby application or library. It has a name (e.g. rake) and a version (e.g. 0.4.16)».
Being very powerful, gems are of great importance in the Rubyland. They can easily be used to extend or modify functionality within Ruby applications.
1.2 Structure
Every gem is different, but most follow a basic structure:
gem/
|-- lib/
| |-- gem.rb
|-- test/
|-- README
|-- Rakefile
|-- gem.gemspec
Your gem’s code is located under lib/ which typically holds a Ruby file with the name of the gem. You can choose to have all the magic happening in this file, but you can also use it to load some other Ruby files also located under lib/, typically inside a folder with the gem’s name. Confused? Have a look:
your_gem/
|-- lib/
| |-- your_gem.rb
| |-- your_gem/
| | |-- source1.rb
| | |-- source2.rb
|-- ...
The test folder’s name is not necessarily named test/. When you’re working with RSpec, for instance, its name is usually spec/. As you’ve probably guessed, this folder holds tests for your gem.
After the README file, which hopefully doesn’t need any introduction, comes the Rakefile. In a gem’s context, the Rakefile is extremely useful. It can hold various tasks to help building, testing and debugging your gem, among all other things that you might find useful.
The gemspec—as the name implies—contains your gem’s specification by defining several attributes. An example gemspec file could be:
Gem::Specification.new do |s|
s.name = "gem"
s.version = "0.0.1"
s.platform = Gem::Platform::RUBY
s.authors = ["Gonçalo Silva"]
s.email = ["goncalossilva@gmail.com"]
s.homepage = "http://github.com/goncalossilva/gem_template"
s.summary = "Sample gem"
s.description = "A gem template"
s.rubyforge_project = s.name
s.required_rubygems_version = ">= 1.3.6"
# If you have runtime dependencies, add them here
# s.add_runtime_dependency "other", "~> 1.2"
# If you have development dependencies, add them here
# s.add_development_dependency "another", "= 0.9"
# The list of files to be contained in the gem
s.files = `git ls-files`.split("\n")
# s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
# s.extensions = `git ls-files ext/extconf.rb`.split("\n")
s.require_path = 'lib'
# For C extensions
# s.extensions = "ext/extconf.rb"
end
Some attributes like the name, version, platform and summary are required. Nonetheless, the vast majority is optional. If you use git with your project, you can use the nifty trick shown above to list the project’s files, executables and extensions. If you don’t, you can simply fall back to using pure Ruby code like:
s.files = Dir["{lib}/**/*.rb", "{lib}/**/*.rake", "{lib}/**/*.yml", "LICENSE", "*.md"]
The dummy gem is very simple. Because of this, it perfectly illustrates some of the ideas explained above. Some interesting bits are shown below:
dummy/
|-- lib/
| |-- dummy/
| | |-- core_ext/
| | | |-- array.rb
| | | |-- string.rb
| | |-- address.rb
| | |-- company.rb
| | |-- ...
| |-- dummy.rb
This gem is organized into several source files inside lib/. The dummy.rb implements the top-level module and loads all functionality from the Ruby files inside lib/dummy/. It also includes some core extensions, namely to the Array and String classes (which are part of Ruby’s core).
1.3 RubyGems
Finally, RubyGems. It is a package manager which became part of the standard library in Ruby 1.9. It allows developers to search, install and build gems, among other features. All of this is done by using the gem command-line utility. You can find its website at rubygems.org.