如何在未安装gem时从require“gem_name”进行救援

时间:2010-01-14 01:02:44

标签: ruby rubygems

我正在编写一个依赖于特定gem的库。我需要宝石并在我的代码中使用它,只要宝石安装在用户的机器上,所有东西都是hunky-dory。但如果不是这样呢?!

我认为这很好,因为我可以从require命令中解救并向输出打印消息以通知用户缺少宝石并优雅地完成它但是我收到错误!

你能告诉我应该怎么做或这段代码有什么问题:

begin 
 require "some_gem"
rescue
 puts "please install some_gem first!" 
end

2 个答案:

答案 0 :(得分:35)

require如果无法加载所需的库,则会引发LoadError异常。但是,您永远不会<{1}}从LoadError进行救援,您可以从StandardError进行救援。

如果你想从LoadError营救,你必须这样说:

begin 
  require 'some_gem'
rescue LoadError
  puts 'please install some_gem first!'
end

更好的是,确保您实际上正在打印正确的缺少的依赖项:

begin 
  require 'some_gem'
rescue LoadError => e
  raise unless e.message =~ /some_gem/
  puts 'please install some_gem first!'
end

(如果异常实际上是由其他地方的某些其他遗失库造成的,那么这会重新引发从中获得的完全相同的异常。你不想打印误导信息,对吗?)

根据库的预期目标受众是什么以及它们是否可能被转储到控制台的回溯吓跑,您可能想要在任何情况下重新引发异常,而不是仅仅吞下它:

begin 
  require 'some_gem'
rescue LoadError => e
  puts 'please install some_gem first!' if e.message =~ /some_gem/
  raise
end

或者,您可以跳过puts,而是将消息设置为您要说的内容而引发异常:

begin 
  require 'some_gem'
rescue LoadError => e
  raise e.exception('please install some_gem first!') if e.message =~ /some_gem/
  raise
end

除非现在异常在错误的位置引发,因此错误的行号和堆栈跟踪因此具有误导性,但这很容易解决:

begin 
  require 'some_gem'
rescue LoadError => e
  raise unless e.message =~ /some_gem/
  friendly_ex = e.exception('please install some_gem first!')
  friendly_ex.set_backtrace(e.backtrace)
  raise friendly_ex
end

现在您打印的内容几乎与使用puts打印的内容完全相同,但是您有一个“正确的”异常,例如允许更好的调试或允许消费者你的图书馆要拯救那个异常并以自己的方式处理它,这两种情况都是不可能的,或者至少很难解决只是吞下异常的解决方案。

答案 1 :(得分:3)

begin
  require "some_gem"
rescue LoadError
  puts "message"
end