2012-05-30 5 views
20

Nie wydaje się, że byłoby to trudne.programowo ustalić, czy dany klejnot jest zainstalowany, a następnie zainstalować go, jeśli nie

Chcę skryptu ruby, który określa, czy jakiś klejnot (jakakolwiek wersja i/lub określona wersja specyfikacji) jest obecnie zainstalowany w systemie (gdziekolwiek będzie wyglądał gem list), a jeśli nie, instaluje go.

Tak, wiem, że w niektórych przypadkach bundler jest w tym świetny. Zaufaj mi, że mam przypadek, w którym z dziwnych powodów nie chcę używać bundlerów. Naprawdę chcę programowo przesłuchać lokalne repozytorium klejnotów.

Jednym ze sposobów programowej instalacji jest po prostu wydostanie się na numer gem install, na pewno.

Ale nie mogę sobie wymyślić wiarygodnego sposobu programowania programowo przesłuchać, aby sprawdzić, czy konkretny klejnot jest zainstalowany, a nie z powłoki, nie z api rubygem, nic.

Czy brakuje mi tego?

Odpowiedz

19
# The version requirements are optional. 
# You can also specify multiple version requirements, just append more at the end 
gem_name, *gem_ver_reqs = 'json', '~> 1.8.0' 
gdep = Gem::Dependency.new(gem_name, *gem_ver_reqs) 
# find latest that satisifies 
found_gspec = gdep.matching_specs.max_by(&:version) 
# instead of using Gem::Dependency, you can also do: 
# Gem::Specification.find_all_by_name(gem_name, *gem_ver_reqs) 

if found_gspec 
    puts "Requirement '#{gdep}' already satisfied by #{found_gspec.name}-#{found_gspec.version}" 
else 
    puts "Requirement '#{gdep}' not satisfied; installing..." 
    # reqs_string will be in the format: "> 1.0, < 1.2" 
    reqs_string = gdep.requirements_list.join(', ') 
    # multi-arg is safer, to avoid injection attacks 
    system('gem', 'install', gem_name, '-v', reqs_string) 
end 

Nowsze wersje rubygems zapewnić API instalatora, więc zamiast wydobyć z kieszeni do komendy gem można również użyć:

# using the same "gdep" variable as above 
Gem.install gem_name, gdep.requirement 

Jednak nie jestem pewien, czy Gem.install względami Twój plik .gemrc.

Istnieje wiele przydatnych metod sprawdzania zainstalowanych klejnotów (patrz rdocs). Niektóre z nich mogą być pomocne:

  • Gem::Specification.find_all_by_name
  • Gem::Requirement#satisfied_by?(gem_version_instance)
  • Gem::Specification#satisfies_requirement?(gem_dependency_instance)
  • Gem.loaded_specs - hash z klejnotów masz faktycznie załadowane metodą gem lub przez require
+1

Doskonała odpowiedź dokładnie to, czego szukałem, dziękuję za dostarczenie przykładów kilku metod API zamiast tylko jednego. Ruby kod rubi api trudno jest uzyskać ogólne zrozumienie, dzięki za przykłady! – jrochkind

0

nie mam pojęcia, czy to jest najlepsze praktyki lub nie, ale:

list = `gem list` 
`gem install builder` unless list.include? "builder" 

... pracował dla mnie w IRB.

+1

byłem szukanie rozwiązania, które nie wymagałoby użycia powłoki poleceń, ale można to zrobić w kodzie ruby. zaakceptowana odpowiedź jest taka: – jrochkind

16

Ostatnia odpowiedź była dobra, ale to jest trochę bardziej precyzyjny:

`gem install redis` unless `gem list`.lines.grep(/^redis \(.*\)/) 

zestawienia tylko gem nazwie redis, a nie inne perełki jak redis-native_hash, lub coś innego.

Innym sposobem, w jaki to widziałem, jest próba nałożenia na to klejnotu.

begin 
    require 'some_crazy_gem' 
rescue LoadError 
    `gem install some_crazy_gem` 
    #... 
end 
+0

Tak, miałem zamiar powiedzieć "Nie, nie ma żadnego klejnotu zaczynającego się" redis "", ale domyślam się, że twoje wyliczenie z przestrzenią w nim jest złapane? Wciąż zdumiewający jest nie mniej odrażający sposób na zrobienie tego. Na przykład nie ma żadnego polecenia, takiego jak "lista klejnotów", ale które zwraca tylko dokładne dopasowania zamiast podłańcuchów? – jrochkind

+1

Możesz również wypróbować 'gem, który nazywa się gem-name'. Jeśli odpowiedź zaczyna się od ERROR, jej nie ma. –

+0

miło, to też jest dobre. Teraz, gdyby istniał tylko sposób na sprawdzenie konkretnej wersji konkretnego klejnotu! To szaleństwo, że rubygems nie ma niezawodnego ruby-api na te wszystkie rzeczy, a każdy ucieka się do skrobania powłoki. – jrochkind