Как узнать, установлен гем в системе или нет?

Как узнать, установлен гем в системе или нет?

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

Есть ли более короткий метод?


person pankajdoharey    schedule 13.12.2011    source источник


Ответы (3)


Если вы пытаетесь сделать это изнутри 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
person Peter Brown    schedule 13.12.2011
comment
Если он не находит данный драгоценный камень, он выдает массу ошибок, как мне с этим справиться? я искал что-то простое, например TRUE или nil. - person pankajdoharey; 13.12.2011
comment
+1 RubyGems — это библиотека Ruby. Раскошелиться на gem из Ruby — это так много разных ошибок. Просто используйте API. - person Jörg W Mittag; 13.12.2011
comment
Правда, даже я хочу использовать библиотеку, но она выдает столько ошибок, когда не находит драгоценный камень. - person pankajdoharey; 13.12.2011
comment
@pankajdoharey Gem::Specification::find_all_by_name возвращает пустой массив, если драгоценный камень не найден. Вы можете добавить empty? в конце, чтобы получить логическое значение. - person Peter Brown; 13.12.2011
comment
@Beerlington на самом деле, find_all_by_name повышает Gem::LoadError, если драгоценный камень не найден (по состоянию на декабрь 2012 г.). Для меня немного загадочно, почему Gem.available? устарел. - person Eric Drechsel; 05.12.2012
comment
@Beerlington ой, ваш последний комментарий верен. Я собираюсь обновить ваш ответ выше. Также ответил здесь. - person Eric Drechsel; 05.12.2012
comment
@EricDrechsel похоже, что ваше изменение было отклонено, но я обновлю ответ. - person Peter Brown; 05.12.2012
comment
Для справки, find_all_by_name поддерживается только с версии 1.9.3: ruby-doc.org/stdlib-1.9.3/libdoc/rubygems/rdoc/Gem/ ----VS---- 1.9.2: ruby-doc.org/stdlib-1.9.2/libdoc/rubygems/rdoc/Gem/ - person inger; 21.10.2013

Я вставляю это в начало моего 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'))

и все прекрасно работает!

person Peter Krnjevic    schedule 11.04.2012

Вот код, который работает для меня. Он также правильно обрабатывает ошибку 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')
person Dylan Northrup    schedule 13.12.2011
comment
Проектировать код вокруг выбрасывания и перехвата ошибок нехорошо. - person Automatico; 25.04.2014
comment
Генерация и перехват ошибок — довольно простая обработка ошибок. Я делаю то же самое, когда пытаюсь открыть файлы, чтобы убедиться, что они были успешно открыты. Я думаю, что за вашим комментарием может быть что-то дополнительное, и был бы рад, если бы вы захотели уточнить или расширить его. - person Dylan Northrup; 25.04.2014
comment
Отлавливание ошибок — это хорошо, когда вы не знаете причину ошибки, но проектировать систему, полагающуюся на отлов ошибок, — нехороший проект. Вы должны скорее создавать методы, которые проверяют, что функция не выдаст ошибку. Если вы, например, используете какую-либо автоматическую систему регистрации ошибок, вы получите огромное количество мусорных ошибок, которые ничего не значат. - person Automatico; 25.04.2014
comment
Мы должны согласиться, чтобы не согласиться. Я знаю, что когда я пытаюсь загрузить драгоценный камень, он либо загружается успешно, либо завершается ошибкой и выдает исключение. Если мне нужно принять решение, основываясь на том, доступны ли методы и данные гема, лучший способ — основывать это решение на том, успешно ли загружен гем. Я не думаю, что нужно изобретать велосипед, чтобы определить успех... если было исключение, драгоценный камень не загружался; если нет исключения, он загружается. Операторы puts здесь потому, что это пример кода. Не стесняйтесь опускать их в производственном коде. - person Dylan Northrup; 28.04.2014
comment
Я действительно думаю, что это тоже вопрос вкуса, и он полностью зависит от области, в которой вы работаете. Но я чувствую, что в целом вы должны стремиться к меньшему количеству попыток уловов, а не к большему. Однако я знаю немало тех, кто предпочитает делать наоборот. Мои мысли, однако: поскольку ruby ​​часто используется с Rails, многие инструменты будут заполнены бессмысленными ошибками и, вероятно, затруднят обнаружение реальных ошибок, на которых вам следует сосредоточиться. - person Automatico; 28.04.2014