检查Ruby Gem可用性

有没有办法通过Gem模块来检查当前是否安装了一些gem? 从Ruby代码,而不是执行“gem列表”…

澄清 – 我不想加载库。 我只是想检查它是否可用,所以所有的rescue LoadError解决scheme不帮助我。 另外我不在乎gem本身是否会起作用,只是它是否被安装。

恕我直言,最好的办法是尝试加载/需要创业板和拯救例外,雷已经显示。 救援LoadErrorexception是安全的,因为它不是由GEM引发的,而是它的标准行为。

您也可以使用gem命令。

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

gem命令与require命令具有相同的行为,只是略有不同。 AFAIK,它仍然试图自动加载主要的GEM文件。

挖掘到rubygems.rb文件(310行)我发现以下执行

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

它可以为您提供一些关于如何在不实际加载库的情况下进行脏检查的提示。

还有:

 Gem.available?('somegem') 

你也可以使用正则expression式。 方便,如果我想允许'rcov'和GitHub变种像'相关性rcov':

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

查看Gem API文档,使用Gem :: Specification :: find_all_by_name来testinggem可用性似乎是合理的。

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

find_all_by_name总是返回一个(Specification对象的)数组,而不是find_by_name ,如果找不到匹配就会引发exception。

既然Gem.available? 被弃用(argh!),你必须再次营救(double aaargh)。 是的,如果找不到gem,find_by_name将引发exception。 所以为了与旧的rubygems向后兼容,常见的解决scheme似乎是:

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

请注意,新的方法允许您传递特定的版本,看看是否加载:

 Gem::Specification.find_by_name('rails', '3.0.4') 

你可以:

 begin require "somegem" rescue LoadError # not installed end 

然而,这不会告诉你模块是否通过gem或其他方式安装。

我使用这个代码,它工作顺利。

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

使用示例

假设您安装了机架1.9.1。

 puts gem_available?('rack') # => true puts gem_available?('rack', '>=2') => # false