Ruby Gem の在庫状況を確認する
質問
Gem モジュールを介して、何らかの gem が現在インストールされているかどうかを確認する方法はありますか?「gem list」を実行するのではなく、Ruby コードから...
明確にするために、ライブラリをロードしたくないのです。利用可能かどうかを確認したいだけなので、 rescue LoadError
解決策は役に立ちません。また、gem 自体が機能するかどうかは気にせず、インストールされているかどうかだけを気にします。
解決
私見の最善の方法は、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?
実際にライブラリをロードせずにダーティ チェックを行う方法についてのヒントが得られます。
他のヒント
もあります:
Gem.available?('somegem')
正規表現も使用できます。 「rcov」と「relevance-rcov」のようなGitHubバリアントを許可する場合に便利です:
Gem.available?(/-?rcov$/)
Gemを使用して、Gem APIドキュメントをご覧ください。 :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
とは異なります。
Gem.availableからですか?非推奨(argh!)であるため、再度レスキューする必要があります(ダブルaaargh)。はい、gemが見つからない場合、find_by_nameは例外をスローします。したがって、古いrubygemsとの後方互換性を保つために、一般的な解決策は次のように思われます:
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')
次のことができます:
begin
require "somegem"
rescue LoadError
# not installed
end
ただし、これは、モジュールがgemまたはその他の方法でインストールされたかどうかを通知しません。
このコードを使用すると、スムーズに動作します。
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