Pergunta

Existe uma maneira de verificar se alguma jóia está actualmente instalado, através do módulo Gem? A partir do código Ruby, não por 'lista gem' execução ...

Para esclarecer - eu não quero carregar a biblioteca. Eu só quero verificar se ele está disponível, por isso, todas as soluções rescue LoadError não me ajudar. Também eu não me importo se o próprio gem vai funcionar ou não, unicamente se ele está instalado.

Foi útil?

Solução

IMHO a melhor maneira é tentar carga / exigem que o GEM e resgatar a exceção, como Ray já mostrou. É seguro para resgatar a exceção LoadError porque não é levantada pelo próprio GEM mas é o comportamento padrão do comando exigem.

Você também pode usar o comando gem vez.

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

O comando gem tem o mesmo comportamento do comando requerem, com algumas pequenas diferenças. AFAIK, ele ainda tenta autoLoad o arquivo GEM principal.

Indo para o arquivo rubygems.rb (linha 310) eu encontrei o seguinte execução

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

Pode fornecer-lhe algumas dicas sobre como fazer uma verificação suja sem realmente carregar a biblioteca.

Outras dicas

Há também:

Gem.available?('somegem')

Você pode usar expressões regex também. Handy se eu quiser permitir 'rcov' e GitHub variantes como 'relevância no rcov':

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

Olhando para a documentação da API Gem, usando Gem: :. Specification :: find_all_by_name para teste de disponibilidade gem parece razoável

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

find_all_by_name sempre retorna uma matriz (Especificação de objetos), em oposição a find_by_name que suscita uma excepção se for encontrada nenhuma correspondência.

Desde Gem.available? está obsoleta (argh!), você tem que salvar novamente (aaargh duplo). Sim, métodos find_by_name_ lança uma exceção se a jóia não foi encontrada. Assim, para ser compatível com versões anteriores com rubygems mais velhos, a solução comum parece ser:

def gem_available?(name)
   Gem::Specification.find_by_name(name)
rescue Gem::LoadError
   false
rescue
   Gem.available?(name)
end

Note que o novo método permite que você passe uma versão específica para ver se que é carregado:

Gem::Specification.find_by_name('rails', '3.0.4')

Você pode:

begin
  require "somegem"
rescue LoadError
  # not installed
end

Este não seria, no entanto, dizer-lhe se o módulo foi instalado através de jóia ou algum outro meio.

Eu uso este código e funciona sem problemas.

def gem_available?(gem_name, version = nil)
  version.nil? gem(gem_name) : gem(gem_name, version)
rescue Gem::LoadError
  false
end

Exemplos de usar

Vamos supor que você acumular 1.9.1 instalado.

puts gem_available?('rack') # => true
puts gem_available?('rack', '>=2') => # false
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top