web-dev-qa-db-ja.com

Ruby Gemの可用性を確認します

Gemモジュールを介して、現在Gemがインストールされているかどうかを確認する方法はありますか? Rubyコードから、「gemリスト」を実行するのではなく......

明確にするために-ライブラリをロードしたくありません。それが利用可能かどうかを確認したいだけなので、すべてのrescue LoadErrorソリューションは私を助けません。また、gem自体が動作するかどうかは気にしません。それがインストールされているかどうかだけです。

42
viraptor

私見の最善の方法は、Rayがすでに示したように、GEMをロード/要求して、例外を救うことです。 LoadError例外はGEM自体によって発生するのではなく、requireコマンドの標準的な動作であるため、レスキューしても安全です。

代わりにgemコマンドを使用することもできます。

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

Gemコマンドの動作はrequireコマンドと同じですが、若干の違いがあります。私の知る限り、それはまだメインのGEMファイルを自動ロードしようとします。

Rubygems.rbファイルを掘り下げる(310行目)次の実行が見つかりました

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

実際にライブラリをロードせずにダーティーチェックを行う方法についてのヒントを提供します。

31
Simone Carletti

またあります:

Gem.available?('somegem')

正規表現も使用できます。 「rcov」や「relevance-rcov」などのGitHubバリアントを許可する場合に便利です。

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

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とは対照的に、常に(仕様オブジェクトの)配列を返します。

37
Eric Drechsel

Gem.availableから?は非推奨です(argh!)。もう一度救助する必要があります(double aaargh)。はい、gemが見つからない場合、find_by_nameは例外をスローします。したがって、古いrubygemとの下位互換性を保つために、一般的な解決策は次のようになります。

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')
29
foz

あなたは出来る:

begin
  require "somegem"
rescue LoadError
  # not installed
end

ただし、これはモジュールがgemまたはその他の方法でインストールされたかどうかを通知しません。

5
Ray Vernagus

私はこのコードを使用し、それはスムーズに動作します。

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
1
androidyue

これはどこにも表示されませんでしたが、あいまいなバージョンの文字列をfind_by_namefind_all_by_nameに渡すこともできます。

Gem::Specification.find_all_by_name('gemname', '>= 4.0').any?
0
lobati