Cómo rescatar un “gem_name” requerido cuando la gem no está instalada

Estoy escribiendo una biblioteca que depende de una gem específica. Necesito la gem y la uso en mi código, y todo es perfecto mientras la gem esté instalada en la máquina del usuario. Pero ¿y si no lo es?

Pensé que está bien porque puedo rescatar el comando de requerimiento e imprimir un mensaje en la salida para informar al usuario sobre la gem que falta y terminarlo con gracia, ¡pero recibo un error!

¿Podría decirme cómo se debe hacer o qué está mal con este código:

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

require genera una excepción LoadError si no puede cargar la biblioteca requerida. Sin embargo, nunca rescata de LoadError ningún lugar, rescata de StandardError .

Si quieres rescatar de LoadError , tienes que decirlo:

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

Aún mejor, asegúrese de que en realidad está imprimiendo la dependencia faltante correcta :

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

(Esto vuelve a generar exactamente la misma excepción de la que se rescató, en caso de que la excepción haya sido causada por alguna otra biblioteca faltante en otro lugar. No querría imprimir información engañosa, ¿verdad?)

Dependiendo de cuál sea el público objective de la biblioteca y de si se puede o no asustar por un rastreo hacia atrás en su consola, es posible que desee volver a boost la excepción en cualquier caso, en lugar de simplemente tragársela:

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

O bien, puede omitir las puts y, en su lugar, generar una excepción con el mensaje configurado para lo que quiere decir:

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

Excepto que ahora la excepción se produce en el lugar equivocado y, por lo tanto, tiene el número de línea y el seguimiento de stack incorrectos y, por lo tanto, es engañosa, pero eso se soluciona fácilmente:

 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 

Ahora imprime casi lo mismo que habría imprimido con las puts , pero tiene una excepción “adecuada” que, por ejemplo, permite una mejor depuración o permite a un consumidor de su biblioteca rescatar esa excepción y manejarla a su manera, ambos lo que hubiera sido imposible o al menos difícil con su solución que simplemente se traga la excepción.

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