Как спасти от обязательного "gem_name", когда гем не установлен - PullRequest
11 голосов
/ 14 января 2010

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

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

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

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

Ответы [ 2 ]

35 голосов
/ 14 января 2010

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

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

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

3 голосов
/ 14 января 2010
begin
  require "some_gem"
rescue LoadError
  puts "message"
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...