Check for Ruby Gem availability

后端 未结 7 1565
没有蜡笔的小新
没有蜡笔的小新 2020-12-02 12:15

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 t

相关标签:
7条回答
  • 2020-12-02 12:43

    Looking at the Gem API documentation, using Gem::Specification::find_all_by_name to test for gem availability seems reasonable.

    if Gem::Specification::find_all_by_name('gemname').any?
      do stuff
    end
    

    find_all_by_name always returns an array (of Specification objects), as opposed to find_by_name which raises an exception if no match is found.

    0 讨论(0)
  • 2020-12-02 12:43

    Since Gem.available? is deprecated (argh!), you have to rescue again (double aaargh). Yes, find_by_name throws an exception if the gem is not found. So to be backwards-compatible with older rubygems, the common solution seems to be :

    def gem_available?(name)
       Gem::Specification.find_by_name(name)
    rescue Gem::LoadError
       false
    rescue
       Gem.available?(name)
    end
    

    Note that the new method allows you to pass a specific version to see if that's loaded:

    Gem::Specification.find_by_name('rails', '3.0.4')
    
    0 讨论(0)
  • 2020-12-02 12:48

    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.

    0 讨论(0)
  • 2020-12-02 12:48

    In Ruby 1.9.3 only there is 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$/)
    
    0 讨论(0)
  • 2020-12-02 12:48

    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.

    0 讨论(0)
  • 2020-12-02 12:55

    I use this code and it works smoothly.

    def gem_available?(gem_name, version = nil)
      version.nil? gem(gem_name) : gem(gem_name, version)
    rescue Gem::LoadError
      false
    end
    

    Examples to use

    Let's assume you have rack 1.9.1 installed.

    puts gem_available?('rack') # => true
    puts gem_available?('rack', '>=2') => # false
    
    0 讨论(0)
提交回复
热议问题