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.
- make a directory
lib
and put a copy ofwhatever.rb
inlib/whatever.rb
. - 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 - 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
% - 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. Sorequire 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
Assign/Replace Params Hash in Rails
Finding If a Sentence Contains a Specific Phrase in Ruby
Check If an Array Is Subset of Another Array in Ruby
Sinatra Clears Session on Post
Why Is Gets Throwing an Error When Arguments Are Passed to My Ruby Script
Heroku App Crash H10 - Bash: Bin/Rails: No Such File or Directory
Converting a Hexadecimal Digest to Base64 in Ruby
Rvm Does Not Install Ruby 1.9.2 on Snow Leopard: 'Error Running 'Make '
Dry Way to Assign Hash Values to an Object
Optional Arguments with Default Value in Ruby
Ruby Array to JSON and Rails JSON Rendering
Traversing a Hash Recursively in Ruby
Allow Public Connections to Local Ruby on Rails Development Server
What Is Your Preferred Way to Produce Charts in a Ruby on Rails Web Application