【问题标题】:Check for Ruby Gem availability检查 Ruby Gem 的可用性
【发布时间】:2010-11-05 03:36:29
【问题描述】:

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

澄清一下 - 我不想加载库。我只想检查它是否可用,所以所有rescue LoadError 解决方案都对我没有帮助。我也不关心 gem 本身是否可以工作,只关心它是否已安装。

【问题讨论】:

    标签: ruby rubygems packages gem


    【解决方案1】:

    你可以:

    begin
      require "somegem"
    rescue LoadError
      # not installed
    end
    

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

    【讨论】:

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

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

    您也可以使用 gem 命令代替。

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

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

    挖掘 ruby​​gems.rb 文件(第 310 行)我发现了以下执行

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

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

    【讨论】:

    • 正确。我将使用的是:Gem.source_index.find_name('some_name').map {|x| x.name} - 它返回匹配的已安装 gem。
    • 使用 $ gem list | grep YOURGEM 检查 YOURGEM 是否存在。
    • GEM::LoadError 应该是Gem::LoadError
    【解决方案3】:

    仅在 Ruby 1.9.3 中还有:

    Gem.available?('somegem')
    

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

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

    【讨论】:

    • 此方法现已弃用:注意:Gem.available?已弃用,请使用 Specification::find_by_name。它将在 2011 年 11 月 1 日或之后删除。
    • 截至今天,Gem::available? 已不复存在。我建议删除这个答案,或者添加一个注释,以免误导人们。
    • 这个答案现在需要被删除。 (Ruby 2.5.1 Gem 不可用?方法)
    【解决方案4】:

    自从 Gem.available 以来?已弃用(啊!),您必须再次救援(双重 aaargh)。是的,如果找不到 gem,find_by_name 会抛出异常。因此,为了向后兼容旧的 ruby​​gems,常见的解决方案似乎是:

    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')
    

    【讨论】:

      【解决方案5】:

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

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

      find_all_by_name 总是返回一个数组(规范对象),而find_by_name 则在找不到匹配项时引发异常。

      【讨论】:

      • 如果您使用的是 ruby​​gems 1.8 或 2.0,这是最佳答案。不需要rescue。或者,您可以使用if ... .any? 来提高可读性。
      【解决方案6】:

      我使用这个代码,它运行顺利。

      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
      

      【讨论】:

        【解决方案7】:

        在这里没有看到这个,但你也可以将模糊版本字符串传递给find_by_namefind_all_by_name

        Gem::Specification.find_all_by_name('gemname', '>= 4.0').any?
        

        【讨论】:

          猜你喜欢
          • 2020-04-23
          • 1970-01-01
          • 1970-01-01
          • 2014-01-15
          • 2014-04-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多