This log covers RubyGems package manager and Ruby Gem. Ruby 1.9 and above ships with RubyGems.

RubyGems

RubyGems is a package manager for Ruby that provoides a standard format for distributing Ruby programs and libraries, a tool designed to easily manage the installation of gems, and a server for distributing them.1

RubyGems2 is similar to apt-get and npm in functionality. It helps to manage Ruby load path (modifies the load path which controls how Ruby code is found by the require statement).

What does gem install do?

Gem is code zimpped up with a little extra data (meta data). gem install do the following tasks3,

  1. Grabs the gem from the source
  2. Puts files into special directory (use gem environment to inspect the path)

Gem installation paths vary from systems.

How does Gem code get required?

Comments from RubyGems sources code kernel_require.rb,

##
# When RubyGems is required, Kernel#require is replaced with our own which
# is capable of loading gems on demand.
#
# When you call <tt>require 'x'</tt>, this is what happens:
# * If the file can be loaded from the existing Ruby loadpath, it
#   is.
# * Otherwise, installed gems are searched for a file that matches.
#   If it's found in gem 'y', that gem is activated (added to the
#   loadpath).
#
# The normal <tt>require</tt> functionality of returning false if
# that file has already been loaded is preserved.

Gems

Gem is like a library or plug-in. It is a simple way to distrubute functionalities.4

Gem contains meta data includes,

  • name
  • version
  • platform

Gem contains components,

  • Code (tests & utilities)
  • documentation
  • Gemspec (meta data mentioned above)

A typical gem file structure,

% tree freewill
freewill/
├── bin/
│   └── freewill
├── lib/
│   └── freewill.rb
├── test/
│   └── test_freewill.rb
├── README
├── Rakefile
└── freewill.gemspec

Using Gems

Two types of gems,

  • Stand-alone Ruby program, e.g. Rails
  • Package like gem, e.g. maruku, a gem convert Markdown to HTML

First type of gems, you can use them in command line like other command line program. For second type of gem, you use require to load the gem code.

require 'maruku'
str = '# Level 1 Heading'
md  = Maruku.new(str)
md.to_html_document

Require

require is a kernel method. It looks in the $LOAD_PATH (arraoy of absolute paths) global variable.5

Ruby Gems are just source code heirarchies insatlled in a directory that ends up in $LOAD_PATH.

In order to require the gem/file, all we need to do is to add the file into the $LOAD_PATH,

lib = File.expand_path("../../lib", __FILE__)
$:.unshift(lib)

$: is equivalent to $LOAD_PATH,

$: == $LOAD_PATH  # -> true

__FILE__, stores the relative path to the current file.

Code snippet below is how Gem (yelp-ruby/yelp.gemspec) add itself into $LOAD_PATH,

# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'yelp/version'

load vs. require

You use load to execute code, and you use require to import libraries. 6

require a lib/gem/file second time does now work, because it prevent redeclaring constants.

  1. https://en.wikipedia.org/wiki/RubyGems

  2. http://guides.rubygems.org/what-is-a-gem/

  3. http://www.justinweiss.com/articles/how-do-gems-work/

  4. http://code.tutsplus.com/articles/ruby-for-newbies-working-with-gems–net-18977

  5. http://joshuapaling.com/blog/2015/03/22/ruby-load-path.html

  6. Metaprogramming Ruby, https://pragprog.com/book/ppmetr2/metaprogramming-ruby-2