未安装gem时如何从require“gem_name”中解救

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

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

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

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

如果无法加载所需的库,则会引发LoadErrorexception。 但是,您从不在任何地方从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 

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

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

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

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

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

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

 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打印的东西相同, 你有一个“正确”的例外,例如允许更好的调试或允许你的库的消费者拯救那个exception并按照他们的方式处理它们,对于只是吞下exception的解决方案来说,这是不可能的,或者至少是难以实现的。

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