views:

1377

answers:

3

Is there a way to check if some gem is currently installed, via the Gem module? From ruby code, not by executing 'gem list'...

To clarify - I don't want to load the library. I just want to check if it's available, so all the 'rescue LoadError' solutions don't help me. Also I don't care if the gem itself will work or not, only whether it's installed.

+1  A: 

You could:

begin
  require "somegem"
rescue LoadError
  # not installed
end

This wouldn't, however, tell you if the module was installed through gem or some other means.

Ray Vernagus
There are two problems here: I don't want to load the library (at least not yet) and I think that will fail if the code in "somegem" throws LoadError for some other reason.
viraptor
+11  A: 

IMHO the best way is to try to load/require the GEM and rescue the Exception, as Ray has already shown. It's safe to rescue the LoadError exception because it's not raised by the GEM itself but it's the standard behavior of the require command.

You can also use the gem command instead.

begin
  gem "somegem"
  # with requirements
  gem "somegem", ">=2.0"
rescue GEM::LoadError
  # not installed
end

The gem command has the same behavior of the require command, with some slight differences. AFAIK, it still tries to autoload the main GEM file.

Digging into the rubygems.rb file (line 310) I found the following execution

matches = Gem.source_index.find_name(gem.name, gem.version_requirements)
report_activate_error(gem) if matches.empty?

It can provide you some hints about how to make a dirty check without actually loading the library.

Simone Carletti
Spot on. What I'll use is: `Gem.source_index.find_name('some_name').map {|x| x.name}` - it returns matching installed gems.
viraptor
+13  A: 

There's also:

Gem.available?('somegem')

You can use regex expressions too. Handy if I want to allow 'rcov' and GitHub variants like 'relevance-rcov':

Gem.available?(/-?rcov$/)
foz