How to require a Ruby gem directly from its path? - ruby

In order to work with rubyzip i installed the gems:
gem install --local rubyzip-1.1.7.gem
gem install --local zip-zip-0.3.gem
In my code i call the gems using the require method:
require 'zip/zip'
require 'zip/filesystem'
I want to use require to load the gems directly from their location on my machine.
i want somthing like this:
require 'path_to_my_zip_gem'
Where path_to_my zip_gem contains the gem files

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

The simpliest answer is
Gem::Specification.find_by_name("GEM_NAME_HERE").full_gem_path
Example
> require File.join(Gem::Specification.find_by_name("railties").full_gem_path, "lib/rails/code_statistics.rb")
=> true

Related

Require local gem ruby

I have a gem that I created in Ruby on my local machine and I need to require this gem in a plain Ruby script that starts a service.
I have to require like this:
require_relative '../../../my-gem/lib/my/gem'
Is it possible to do this require without putting in the relative path?
require checks for files in $LOAD_PATH. You can put your gem in one of those directories in order to require it directly. If you don't like your load path, you can add a new directory to it in your script, or set the RUBYLIB environment variable which is added to the load path.
If you have a gem, you can install it and set the version you want (in my example 1.0.0.beta) with gem 'my-gem', '= 1.0.0.beta'.
But I think yu look for another solution:
You can extend the location where require looks:
$:.unshift('../../../my-gem/lib')
require('my/gem')
or
$LOAD_PATH.unshift('../../../my-gem/lib')
require('my/gem')
You could also use $: << '../../../my-gem/lib', but I prefer unshift. If your gem contains a file with similar names as in a gem (avoid it!), then unshift guarantees your script is loaded.

ruby adds no path to gems

I use:
rvm 1.25.19 (stable)
ruby 1.9.3p545
I install gem rake command
gem install rake
I understand that $LOAD_PATH should contain the paths:
~/.rvm/rubies/ruby1.9/gems/rake/lib
~/.rvm/rubies/ruby1.9/gems/rake/bin
I execute command:
ruby -e 'puts $LOAD_PATH'
output:
/home/slip/.rvm/rubies/ruby-1.9.3-p545/lib/ruby/site_ruby/1.9.1
/home/slip/.rvm/rubies/ruby-1.9.3-p545/lib/ruby/site_ruby/1.9.1/x86_64-linux
/home/slip/.rvm/rubies/ruby-1.9.3-p545/lib/ruby/site_ruby
/home/slip/.rvm/rubies/ruby-1.9.3-p545/lib/ruby/vendor_ruby/1.9.1
/home/slip/.rvm/rubies/ruby-1.9.3-p545/lib/ruby/vendor_ruby/1.9.1/x86_64-linux
/home/slip/.rvm/rubies/ruby-1.9.3-p545/lib/ruby/vendor_ruby
/home/slip/.rvm/rubies/ruby-1.9.3-p545/lib/ruby/1.9.1
/home/slip/.rvm/rubies/ruby-1.9.3-p545/lib/ruby/1.9.1/x86_64-linux
why path to gem 'rake' don't add?
Installing a gem in Ruby doesn’t automatically add that gem’s files to the load path. When you require a file, first the existing load path is searched and if no matching file is found then Rubygems searches the installed gems for the file. If such a gem is found, then it is activated, which is when the gem’s lib directory is added to the load path.
Here’s an example using the Haml gem:
puts "Before:"
puts $LOAD_PATH
puts
require 'haml'
puts "After:"
puts $LOAD_PATH
This produces:
Before:
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/site_ruby/1.9.1
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/site_ruby/1.9.1/x86_64-darwin10.8.0
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/site_ruby
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/vendor_ruby/1.9.1
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/vendor_ruby/1.9.1/x86_64-darwin10.8.0
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/vendor_ruby
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/x86_64-darwin10.8.0
After:
/Users/matt/.rvm/gems/ruby-1.9.3-p448/gems/tilt-1.4.1/lib
/Users/matt/.rvm/gems/ruby-1.9.3-p448/gems/haml-4.0.5/lib
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/site_ruby/1.9.1
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/site_ruby/1.9.1/x86_64-darwin10.8.0
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/site_ruby
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/vendor_ruby/1.9.1
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/vendor_ruby/1.9.1/x86_64-darwin10.8.0
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/vendor_ruby
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1
/Users/matt/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/x86_64-darwin10.8.0
See how the lib directories for Tilt (which is a dependency of Haml) and Haml have been added to the start of the load path.
In the case of some gems, such as Rake, this is complicated by the fact they are part of the standard library and so are already on the load path. If you changed the example above to use require 'rake' then you wouldn’t see any change in the load path. In this situation you can specify you want to use the gem version with the gem method. This activates the gem in question, placing its lib directory at the start of the load path so when you later call require you will load the correct version.
For example, this script
require 'rake'
puts Rake::VERSION
produces 0.9.2.2 with Ruby 1.9.3, as that is the version of Rake included in the standard library. However this script:
gem 'rake'
require 'rake'
puts Rake::VERSION
produces 10.1.1, since that is the current highest version of the Rake gem installed on my system. You can also specify a particular gem version by providing a second argument to gem (this is the same syntax as used in Gemfiles). Note that the gem method doesn’t require any files, you have to do that as a separate step.

Created a simple gem, but irb can't see it

I created a simple gem by doing:
testgem.gemspec
Gem::Specification.new do |s|
s.name = 'testgem'
s.version = '0.0.1'
s.summary = "code generation"
s.authors = ['asdf']
end
created the following file layout:
testgem.gemspec
Gemfile
lib/
lib/testgem.rb
lib/testgem/other.rb
ran the following:
gem build testgem.gemspec
WARNING: no description specified
WARNING: no email specified
WARNING: no homepage specified
Successfully built RubyGem
Name: testgem
Version: 0.0.1
File: testgem-0.0.1.gem
installed it:
gem install ./testgem-0.0.1.gem
Successfully installed testgem-0.0.1
1 gem installed
tested to see if irb can see it:
irb
require 'testgem'
oadError: cannot load such file -- testgem
I'm using Ruby 1.9.3-p194
It seems to be installed if I do:
gem list
..
testgem (0.0.1)
..
What could be the issue?
You need to add your lib to the search path. Just add
$:.push File.expand_path("../lib", __FILE__)
on top of your .gemspec
When you use require in Ruby, you are trying to load a file, not a gem. The file could of course be contained in a gem, and by convention a gem will have a file with the same name as the gem itself so that if you wanted to use the gem foo you would use require 'foo'. This isn’t always the case though, for example to use the bcrypt-ruby gem you need to require 'bcrypt'.
Additionally a gem doesn’t necessarily have to contain any filles at all. An example of this is the rails gem, which doesn’t contain any files itself (at least in version 3.2), but has dependencies to the various Rails components, so that you can install them all in one step.
In your case, although you have a lib/testgem.rb file in your gems project directory, you are not including it in your gem. You need to specify which files should be included, the default is to not include anything.
To simply include all the files in your project directory, you can add something like:
s.files = Dir.glob '**/*'
to your gemspec.
You need to require 'rubygems' first.

Strange require statement errors in Ruby?

I've got a wrapper for my Gem, socks, inside socks.rb. The entire file is made up of require statements, and a module declaration:
# lib/socks.rb
require 'socks/version'
require 'socks/base_controller'
require 'socks/templates'
require 'socks/tasks'
require 'socks/rake_tasks'
module Socks
end
However, require 'socks/tasks' and socks/rake_tasks is giving me a LoadError: no such file to load -- socks/tasks / rake_tasks error.
Is this a problem with the alignment of the require statements, or just the code?
Code is on Github: https://github.com/Beakr/socks
EDIT: require './socks/tasks' is now working, however require './socks/rake_tasks' is not.
Ruby load files using its $LOAD_PATH. This global array is changed by e.g. rubygems and bundler to allow to find libraries in various locations. In your sock.gemspec you have defined
gem.require_paths = ["lib"]
which means that rubygems will add the lib directory of your gem to ruby's $LOAD_PATH. But it odes so only if you have installed the gem and the gemspec is thus evaluated. If you don't want to install your gem, you can test your gem using
bundle exec irb
in your gem directory, or alternatively by first adapting your $LOAD_PATH in your irb session like so:
$LOAD_PATH.push "/path/to/your/gem/lib"
require 'socks'

Add the gem I'm developing to be loaded automatically by rubygems without build/install?

I'm developing a gem with Jeweler in a custom directory.
I want to be able to require the gem within any app (and also the executables files from $PATH), and without needing to build and install the gem each time I modify it.
I thought about 2 ways:
I make a symlink to $GEM_HOME/gems and $GEM_HOME/bin
I add the bin directory to $PATH and the lib directory to rubygems to be loaded.
But I bet there is a proper way to do this.
You can specify a local path in the gem command:
gem 'your-gem', '1.2.3', :path => 'path/to/your-gem'
Update: As #Nick points out in the comments,
This is specific to using bundler. In general, it's just require '/path/to/your-gem.
I'd like to add, however, that if you're using a custom-developed gem, bundle will probably make your life easier if you're not already using it. This is because with bundler, when you're done developing the gem (or at a stable/release point) you can load a gem directly from a github repository like this:
gem 'your-gem', :git => 'git#github.com:you/your-gem.git'
No need to mess around with your Gemfile
require 'bundler/setup' will put the right gem into your $LOAD_PATH and allow you to require it on the next line.
#!/usr/bin/env ruby
require 'bundler/setup'
require '<gem-name>'

Resources