How Does Require Rubygems Help Find Rubygem Files

How do you get a ruby gem into the include path for require

It's actually not to hard to do this manually. Let's say you have a library whatever.rb that you want to distribute as a gem.

  1. make a directory lib and put a copy of whatever.rb in lib/whatever.rb.
  2. make a file whatever.gemspec, and put the following in there, filling in the appropriate values:

    Gem::Specification.new do |spec|
    spec.name = 'the-name-of-your-gem'
    spec.version ='0.0.1'

    # this is important - it specifies which files to include in the gem.
    spec.files = ["lib/whatever.rb"]

    # optional, but useful to your users
    spec.summary = "A more longwinded description of your gem"
    spec.author = 'Your Name'
    spec.email = 'you@yourdomain.com'
    spec.homepage = 'http://www.yourpage.com'

    # you did document with RDoc, right?
    spec.has_rdoc = true

    # if you have a ruby forge project
    spec.rubyforge_project = 'your-project-name-on-rubyforge'

    # if you have any dependencies on other gems, list them thusly
    spec.add_dependency('hpricot')
    spec.add_dependency('log4r', '>= 1.0.5')
    end
  3. now, to build the gem, use the gem build command:

    % gem build whatever.gemspec
    Successfully built RubyGem
    Name: the-name-of-your-gem
    Version: 0.0.1
    File: the-name-of-your-gem-0.0.1.gem
    %
  4. You can test locally by using gem install the-name-of-your-gem-0.0.1.gem
    To use your library in a script then, simply do the following at the top:

    require 'rubygems' # puts gem libraries in the require path
    require 'whatever' # loads your library

For more on what the various settings in the gemspec file, check the GemSpec Reference.

Personally, I use rubygems a lot to package executable scripts as well, and find it very handy for that.

How can I see files inside a Ruby .gem?


with gem unpack

You can use the gem unpack command to extract the contents of a .gem file into a directory. Assuming you have some_file.gem:

gem unpack some_file.gem

with tar

If you want to list the gem's contents without unpacking it, you can use tar (a .gem file is just a .tar file with a specific format).

tar --to-stdout -xf some_file.gem data.tar.gz | tar -zt

Here's a longer explanation of how this works:

# Download a .gem file
$ gem fetch json_pure -v '2.0.3'
Fetching: json_pure-2.0.3.gem (100%)
Downloaded json_pure-2.0.3

# List the contents of the gem
# You can see that it contains separate files for metadata, the gem files, and a checksum
$ tar -tf json_pure-2.0.3.gem
metadata.gz
data.tar.gz
checksums.yaml.gz

# Extract just the data.tar.gz file, then unzip and list the contents of *that* file.
# --to-stdout so we can pipe it to another command
# -x extract
# -f file
#
# Then:
# -z use gunzip to decompress the .tar.gz file
# -t list the contents of the archive
tar --to-stdout -xf json_pure-2.0.3.gem data.tar.gz | tar -zt
./tests/test_helper.rb
.gitignore
.travis.yml
CHANGES.md
Gemfile
...

In most cases gem unpack is probably what you want. The main benefit to the tar command above is that it doesn't create any new directories or actually unpack the files. It might also be useful if you don't have rubygems installed.

How to find where gem files are installed

Use gem environment to find out about your gem environment:

RubyGems Environment:
- RUBYGEMS VERSION: 2.1.5
- RUBY VERSION: 2.0.0 (2013-06-27 patchlevel 247) [x86_64-darwin12.4.0]
- INSTALLATION DIRECTORY: /Users/ttm/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0
- RUBY EXECUTABLE: /Users/ttm/.rbenv/versions/2.0.0-p247/bin/ruby
- EXECUTABLE DIRECTORY: /Users/ttm/.rbenv/versions/2.0.0-p247/bin
- SPEC CACHE DIRECTORY: /Users/ttm/.gem/specs
- RUBYGEMS PLATFORMS:
- ruby
- x86_64-darwin-12
- GEM PATHS:
- /Users/ttm/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0
- /Users/ttm/.gem/ruby/2.0.0
- GEM CONFIGURATION:
- :update_sources => true
- :verbose => true
- :backtrace => false
- :bulk_threshold => 1000
- REMOTE SOURCES:
- https://rubygems.org/
- SHELL PATH:
- /Users/ttm/.rbenv/versions/2.0.0-p247/bin
- /Users/ttm/.rbenv/libexec
- /Users/ttm/.rbenv/plugins/ruby-build/bin
- /Users/ttm/perl5/perlbrew/bin
- /Users/ttm/perl5/perlbrew/perls/perl-5.18.1/bin
- /Users/ttm/.pyenv/shims
- /Users/ttm/.pyenv/bin
- /Users/ttm/.rbenv/shims
- /Users/ttm/.rbenv/bin
- /Users/ttm/bin
- /usr/local/mysql-5.6.12-osx10.7-x86_64/bin
- /Users/ttm/libsmi/bin
- /usr/local/bin
- /usr/bin
- /bin
- /usr/sbin
- /sbin
- /usr/local/bin

Notice the two sections for:

  • INSTALLATION DIRECTORY
  • GEM PATHS

When is the 'require' necessary when using a ruby gem?

Usually, an application that is using a gem needs to require the gem:

require "my_awesome_gem"
MyAwesomeGem.do_something_great

However, if an application is using bundler, which defines the application's gem in a file called "Gemfile":

source 'http://rubygems.org'
gem 'my_awesome_gem'

then the application may invoke bundler in a way that automatically requires all of the gems specified in the Gemfile:

require "bundler"
Bundler.require
MyAwesomeGem.do_something_great

Rails projects use Bundler.require, so a Rails application will not need to explicitly require a gem in order to use it: Just add the gem to the Gemfile and go.

For more about Bundler.require, see the bundler documentation

For more about how Rails uses Bundler, see How Does Rails Handle Gems? by Justin Weiss.

How to require ruby gem from a specific location?

Look carefully at how $LOAD_PATH is configured for each gem after you include it. Normally it's the full path to where the base gemname.rb is located, like in your case where rugged.rb is.

The way the $LOAD_PATH works is it scans through that list looking for rugged.rb and if it doesn't find it, moves on to the next possible location. You're specifying a directory which doesn't have that, so find the right path and fill that in, and you should be good.

I have a gem installed but require 'gemname' does not work. Why?

There is no standard for what the file you need to include is. However there are some commonly followed conventions that you can can follow try and make use of:

  • Often the file is called the same
    name as the gem. So require mygem
    will work.
  • Often the file is
    the only .rb file in the lib
    subdirectory of the gem, So if you
    can get the name of the gem (maybe
    you are itterating through
    vendor/gems in a pre 2.1 rails
    project), then you can inspect
    #{gemname}/lib for .rb files, and
    if there is only one, its a pretty
    good bet that is the one to require

If all of that works, then all you can do is look into the gem's directory (which you can find by running gem environment | grep INSTALLATION | awk '{print $4}' and looking in the lib directory, You will probably need to read the files and hope there is a comment explaining what to do

How to require a Ruby gem directly from its path?

Basically, it's because require method loads files by name from paths listed in $: or $LOAD_PATH

"If the filename does not resolve to an absolute path, it will be
searched for in the directories listed in $LOAD_PATH ($:)."

http://ruby-doc.org/core-2.2.2/Kernel.html#method-i-require

If you want to require a gem from the "local" path then the require_relative method could help since you can specify a path relative to the requiring file’s path. Look at the official documentation for further details:

http://ruby-doc.org/core-2.2.2/Kernel.html#method-i-require_relative

How to include data files in a Ruby Gem?

Suppose you have a project structure like this:

bin/
|__ foobar*
lib/
|__ foobar/
| |__ templates/
| | |__ a/
| | |__ b/
|___|__ meta.rb
|___|__ utils.rb

In lib/foobar/teplates directory you have your template directories or
files.

lib/foobar/meta.rb file contains the name of your project and its
version. It's important to keep them (particularly a version number)
synced with the name & the version of the project in your gem
specification. (The best way to do this is read meta.rb from Rakefile
to pass values to the spec.)

For example, meta.rb may look like:

module Foobar
module Meta
NAME = 'foobar'
VERSION = '0.1.2'
end
end

Then write a function that return a full path to the lib directory
regardless whether you are testing your project from the sources
directory or the project is installed from the rubygems.

utils.rb:

require_relative 'meta'

module Foobar
module Utils

# Return a directory with the project libraries.
def self.gem_libdir
t = ["#{File.dirname(File.expand_path($0))}/../lib/#{Meta::NAME}",
"#{Gem.dir}/gems/#{Meta::NAME}-#{Meta::VERSION}/lib/#{Meta::NAME}"]
t.each {|i| return i if File.readable?(i) }
raise "both paths are invalid: #{t}"
end

# [...]
end
end

Having Foobar::Utils.gem_libdir function you can always read your
templates in bin/foobar file:

require_relative '../lib/foobar/utils'

puts Dir[Foobar::Utils.gem_libdir + '/*']
puts Foobar::Utils.gem_libdir + '/templates/a/blah-blah'


Related Topics



Leave a reply



Submit