【问题标题】:How do I find out whether a gem is installed in the system or not?如何确定系统中是否安装了 gem?
【发布时间】:2012-12-05 06:28:51
【问题描述】:

如何查看系统中是否安装了 gem?

%x('gem' 'list').split.find{|i| i == "capybara"}

有没有更短的方法?

【问题讨论】:

    标签: ruby rubygems gem


    【解决方案1】:

    如果您尝试在 ruby​​ 中执行此操作,您可以使用内置的 RubyGem 方法。较早的版本提供了一个返回布尔值的Gem.available?('capybara') 方法,但这已被弃用。现在推荐的方式是使用(假设您使用的是支持它的版本):

    Gem::Specification::find_by_name('capybara')
    

    http://rubygems.rubyforge.org/rubygems-update/Gem/Specification.html

    更新

    如果你想要一个布尔结果,你可以使用.find_all_by_name() 并检查结果数组是否为空:

    if Gem::Specification::find_all_by_name('capybara').any?
      # Gem is available
    end
    

    【讨论】:

    • 如果它没有找到给定的 gem,它会产生大量错误,我该如何处理?我在寻找简单的东西,比如 TRUE 或 nil。
    • +1 RubyGems 是一个 Ruby 库。从 Ruby 向gem 发起攻击是非常多不同的错误。只需使用 API。
    • 是的,即使我想使用库,但是当它找不到 gem 时会出现很多错误
    • @pankajdoharey Gem::Specification::find_all_by_name 如果找不到 gem,则返回一个空数组。您可以在末尾添加 empty? 以获得布尔值。
    • @Beerlington 实际上,如果找不到 gem(截至 2012 年 12 月),find_all_by_name 会引发 Gem::LoadError。为什么Gem.available? 被弃用对我来说有点神秘。
    【解决方案2】:
    %x('gem' 'list' | 'grep' 'capybara').empty?
    

    【讨论】:

      【解决方案3】:

      我把它放在我的 Gemfile 的开头:

      def gem_available?(gemname)
        if Gem::Specification.methods.include?(:find_all_by_name) 
          not Gem::Specification.find_all_by_name(gemname).empty?
         else
           Gem.available?(gemname)
         end
       end
      

      然后只需使用:

      if (gem_available?('gem_i_need'))
      

      一切正常!

      【讨论】:

        【解决方案4】:

        这里有一些适合我的代码。它还可以正确处理当您尝试加载无法找到的 gem 时抛出的 Gem::LoadError

        require 'rubygems'
        
        def can_we_find_gem(gem_name)
          found_gem = false
          begin
            found_gem = Gem::Specification.find_by_name(gem_name)
          rescue Gem::LoadError
            puts "Could not find gem '#{gem_name}'"
          else
            puts "Found gem '#{gem_name}'"
          end
        end
        
        can_we_find_gem('chef')
        can_we_find_gem('not-chef')
        

        【讨论】:

        • 围绕抛出和捕获错误设计代码并不好。
        • 抛出和捕获错误是非常基本的错误处理。当我尝试打开文件以查看它们是否已成功打开时,我会做同样的事情。我认为您的评论背后可能还有其他内容,如果您想澄清或扩展它,我会很高兴。
        • 在不知道错误原因的情况下捕获错误是好的,但是将系统设计为依赖于捕获错误并不是好的设计。您应该创建验证函数不会引发错误的方法。例如,如果您使用一些自动错误记录系统,您最终会遇到大量没有任何意义的垃圾错误。
        • 我们必须同意不同意。我知道当我尝试加载 gem 时,它要么加载成功,要么失败并抛出异常。如果我需要根据 gem 的方法和数据是否可用来做出决定,最好的方法是根据 gem 是否成功加载来做出决定。我认为没有必要重新发明轮子来做出成功的决定……如果有异常,宝石就不会加载;如果没有例外,它加载。那里的puts 语句是因为这是示例代码。随意在生产代码中省略它们。
        • 我确实认为这也是一个品味问题,并且完全取决于你工作的领域。但我觉得总的来说,你应该转向更少的尝试捕获而不是更多。但是,我确实知道很多人喜欢做相反的事情。不过我的想法是:因为 ruby​​ 经常与 Rails 一起使用,所以许多工具会充满无意义的错误,并且可能更难发现你应该关注的实际错误。
        猜你喜欢
        • 2013-04-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-08
        • 2021-01-04
        • 1970-01-01
        • 2016-11-28
        • 1970-01-01
        相关资源
        最近更新 更多