Andreas Krey
Andreas Krey

Reputation: 6764

Set GEM_HOME/PATH or Gem.path programmatically

I'm using a gem that comes with my program, and I simply do

Gem.path.insert(0, basedir + '/packages/lib')

and it works (basedir is set already). Now this works with the older ruby we have (ruby 2.0.0p247 on rhel5, not in /usr/bin).

We have other machines with rhel7 where /usr/bin/ruby is ruby 2.0.0p353, and there the same code does not work - some gems fail to be required.

There (and on the old machs as well)

ENV['GEM_HOME'] = basedir + '/packages/lib'
Gem.clear_paths

works, but this is totally ugly.

Why doesn't the Gem.path.insert work here, and what would be portable? (Neither GEM_PATH nor GEM_HOME are set.)

Upvotes: 3

Views: 2675

Answers (1)

xoryves
xoryves

Reputation: 1476

You should use Gem.paths=. It calls Gem.clear_paths for you and initializes the needed variables.

Gem.paths = {
    'GEM_HOME' => '/opt/rubygems/ruby',
    'GEM_PATH' => '/opt/rubygems/ruby:/opt/rubygems/2.0'
}
# for your example
Gem.paths = { 'GEM_HOME' => "#{basedir}/packages/lib" }

If you only need one Gem or a Ruby library that is not shipped as a Gem, then just include it's lib folder to $LOAD_PATH.

$LOAD_PATH << '/opt/rubygems/ruby/gems/name-0.1.2/lib'
# for your example
$LOAD_PATH.unshift "#{basedir}/packages/lib"

A workaround for you would be the following, but I recommend setting Gem.paths or adding to $LOAD_PATH.

Gem.path.insert(0, basedir + '/packages/lib')
Gem::Specification.dirs << "#{basedir}/packages/lib/specifications'

I have tested Gem.path.insert with ruby-2.0.0p247, ruby-2.0.0p353 (both self compiled) and ruby-2.0.0p353 (CentOS RPM 2.0.0.353-20.el7). The self compiled and Ruby 2.1.3p242 from openSUSE 13.2 works. The CentOS Ruby doesn't work for me eather, because it calls Gem::Specification.dirs before the interpreter reaches the Gem.path.insert line. Don't know why the CentOS and RHEL RPMs behaves different from a clean build or openSUSE RPMs.

ruby compiled from source calls:
--------------------------------
Gem.clear_paths

ruby from CentOS7 calls:
-----------------
Gem.clear_paths
Gem::Specification.dirs
Gem.path
Gem.paths

The following is a list of what gets called on a require.

So, if Gem::Specification.dirs is called before the custom path is inserted to Gem.path, the Rubygem library doesn't know to look at the custom folder's specifications path.

Upvotes: 9

Related Questions