Проверить наличие Ruby Gem - PullRequest
41 голосов
/ 23 июня 2009

Есть ли способ проверить, установлен ли какой-либо драгоценный камень в данный момент через модуль Gem? Из кода ruby, а не путем выполнения 'списка драгоценных камней' ...

Чтобы уточнить - я не хочу загружать библиотеку. Я просто хочу проверить, доступна ли она, поэтому все решения rescue LoadError мне не помогают. Кроме того, мне все равно, будет ли работать сам драгоценный камень или нет, только если он установлен.

Ответы [ 6 ]

39 голосов
/ 15 сентября 2009

Также есть:

Gem.available?('somegem')

Вы также можете использовать выражения регулярных выражений. Удобно, если я хочу разрешить варианты 'rcov' и GitHub, такие как 'релевантность-rcov':

Gem.available?(/-?rcov$/)
34 голосов
/ 05 декабря 2012

Глядя на документацию по 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, который вызывает исключение, если совпадение не найдено.

31 голосов
/ 23 июня 2009

ИМХО, лучший способ - попытаться загрузить / запросить GEM и спасти Исключение, как уже показал Рэй. Безопасно спасти исключение LoadError, потому что оно не вызывается самим GEM, но это стандартное поведение команды require.

Вместо этого вы также можете использовать команду 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?

Он может дать вам несколько советов о том, как выполнить грязную проверку без фактической загрузки библиотеки.

29 голосов
/ 17 сентября 2011

С Gem.available? устарела (argh!), вы должны снова спасти (double aaargh). Да, find_by_name выдает исключение, если гем не найден. Таким образом, для обратной совместимости со старыми рубинами, общее решение выглядит следующим образом:

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')
4 голосов
/ 23 июня 2009

Вы могли бы:

begin
  require "somegem"
rescue LoadError
  # not installed
end

Однако это не скажет вам, был ли модуль установлен с помощью gem или других средств.

1 голос
/ 19 августа 2014

Я использую этот код, и он работает гладко.

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
...