Как спасти от необходимости "gem_name", когда камень не установлен

Я пишу библиотеку, которая зависит от конкретного драгоценного камня. Я требую драгоценный камень и использую его в своем коде, и все очень сложно, пока камень установлен на машине пользователя. но что, если это не так?!

Я думал, что это нормально, потому что я могу избавиться от команды require и напечатать сообщение на выходе, чтобы сообщить пользователю о недостающем камне и закончить его изящно, но я получаю сообщение об ошибке!

Не могли бы вы рассказать мне, как это должно быть сделано или что не так с этим фрагментом кода:

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

Ответ 1

require вызывает исключение LoadError, если он не может загрузить нужную библиотеку. Однако вы никогда не спасаетесь от 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

Кроме того, исключение возникает не в том месте и, следовательно, имеет неправильный номер строки и stacktrace и, таким образом, вводит в заблуждение, но это легко фиксируется:

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, но у вас есть "правильное" исключение, которое, например, позволяет лучше отлаживать или позволяет потребителю вашей библиотеки восстанавливать это исключение и обрабатывать его их путь, оба из которых были бы невозможны или, по крайней мере, жесткие с вашим решением, которое просто проглатывает исключение.

Ответ 2

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