检查Ruby Gem的可用性

vir*_*tor 42 ruby gem rubygems packages

有没有办法通过Gem模块检查当前是否安装了某些gem?从ruby代码,而不是通过执行'宝石列表'...

澄清 - 我不想加载库.我只是想检查它是否可用,所以所有的rescue LoadError解决方案都没有帮助我.此外,我不在乎宝石本身是否有效,只是它是否已安装.

foz*_*foz 38

还有:

Gem.available?('somegem')
Run Code Online (Sandbox Code Playgroud)

您也可以使用正则表达式.如果我想允许'rcov'和GitHub变体如'relevant-rcov',我会很方便:

Gem.available?(/-?rcov$/)
Run Code Online (Sandbox Code Playgroud)

  • 现在不推荐使用此方法:注意:Gem.available?不推荐使用,请使用Specification :: find_by_name.它将在2011-11-01之后或之后删除. (26认同)
  • 截至今天,`Gem :: available?`已经不见了.我建议删除这个答案,或添加一个注释,以免误导人. (2认同)

Eri*_*sel 35

查看Gem API文档,使用Gem :: Specification :: find_all_by_name来测试gem的可用性似乎是合理的.

if Gem::Specification::find_all_by_name('gemname').any?
  do stuff
end
Run Code Online (Sandbox Code Playgroud)

find_all_by_name总是返回一个(规范对象)数组,相反,find_by_name如果没有找到匹配则引发异常.

  • 如果您使用的是rubygems 1.8或2.0,这是最好的答案.不需要"救援".或者,你可以使用`if` ...`.any?`来提高可读性. (4认同)

Sim*_*tti 31

恕我直言,最好的方法是尝试加载/要求GEM并拯救Exception,正如Ray已经表明的那样.抢救LoadError异常是安全的,因为它不是由GEM本身引发的,而是require命令的标准行为.

您也可以使用gem命令.

begin
  gem "somegem"
  # with requirements
  gem "somegem", ">=2.0"
rescue Gem::LoadError
  # not installed
end
Run Code Online (Sandbox Code Playgroud)

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?
Run Code Online (Sandbox Code Playgroud)

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


foz*_*foz 29

Gem.available?不赞成(唉!),你必须再次营救(双aaargh).是的,如果找不到gem,find_by_name会抛出异常.因此,为了与旧的rubygems向后兼容,常见的解决方案似乎是:

def gem_available?(name)
   Gem::Specification.find_by_name(name)
rescue Gem::LoadError
   false
rescue
   Gem.available?(name)
end
Run Code Online (Sandbox Code Playgroud)

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

Gem::Specification.find_by_name('rails', '3.0.4')
Run Code Online (Sandbox Code Playgroud)


Ray*_*gus 6

你可以:

begin
  require "somegem"
rescue LoadError
  # not installed
end
Run Code Online (Sandbox Code Playgroud)

但是,这不会告诉您模块是通过 gem 还是其他方式安装的。

  • 这里有两个问题:我不想加载库(至少现在还没有),我认为如果“somegem”中的代码由于其他原因抛出 LoadError 会失败。 (2认同)