Ruby имеет два разных механизма исключения: Throw/Catch and Raise/Rescue.
Почему у нас есть два?
Когда вы должны использовать один, а не другой?
Ruby имеет два разных механизма исключения: Throw/Catch and Raise/Rescue.
Почему у нас есть два?
Когда вы должны использовать один, а не другой?
Я думаю, http://hasno.info/ruby-gotchas-and-caveats имеет достойное объяснение разницы:
catch/throw - это не то же самое, что рейз/спасение. catch/throw позволяет быстро выходить из блоков обратно в точку, где улов определен для определенного символа, повышение спасения - это реальный материал обработки исключений, включающий объект Exception.
raise, fail, rescue и ensure обрабатывать  ошибки, также известные как  исключенияthrow и catch  поток управленияВ отличие от других языки, Rubys throw и catch не используются для исключений. Вместо этого они предоставляют способ прекратить выполнение раньше, когда нет необходима дальнейшая работа. (Grimm, 2011)
Прекращение одного уровня потока управления, как и цикл while, может быть выполнено с помощью простого return. Завершение многих уровней управляющего потока, например вложенного цикла, может быть выполнено с помощью throw.
В то время как механизм исключения для повышения и спасения отлично подходит для отказа от выполнения, когда что-то идет не так, иногда бывает приятно выпрыгнуть из какой-то глубоко вложенной конструкции во время нормальной обработки. Это - то, где поймать и бросить пригодится. (Thomas and Hunt, 2001)
https://coderwall.com/p/lhkkug/don-t-confuse-ruby-s-throw-statement-with-raise предлагает отличное объяснение, которое, я сомневаюсь, я могу улучшить. Подводя итог, нажимая некоторые образцы кода из сообщения в блоге, когда я иду:
 raise/rescue являются ближайшими аналогами конструкции throw/catch, с которой вы знакомы с других языков (или с Python raise/except). Если вы столкнулись с условием ошибки, и вы бы throw над ним на другом языке, вы должны raise в Ruby.
Ruby throw/catch позволяет вам выполнить выполнение и поднять стек, ищущий catch (например, raise/rescue), но на самом деле не предназначен для условий ошибки, Его следует использовать редко, и существует только тот момент, когда "подойти к стеку, пока вы не найдете соответствующее поведение catch", имеет смысл для алгоритма, который вы пишете, но не имеет смысла думать о throw как соответствующее условию ошибки.
 Что такое catch и throw, используемый в Ruby? предлагает несколько предложений о хорошем использовании конструкции throw/catch.
Конкретные поведенческие различия между ними включают:
 rescue Foo приведет к спасению экземпляров Foo, включая подклассы Foo. catch(foo) будет захватывать только один объект, Foo. Вы не только не можете передать catch имя класса, чтобы поймать его экземпляры, но даже не проверите сравнения равенств. Например,
catch("foo") do
  throw "foo"
end
предоставит вам UncaughtThrowError: uncaught throw "foo" (или ArgumentError в версиях Ruby до 2.2)
Можно указать несколько предложений о спасении...
begin
  do_something_error_prone
rescue AParticularKindOfError
  # Insert heroism here.
rescue
  write_to_error_log
  raise
end
 в то время как несколько catch es должны быть вложенными...
catch :foo do
  catch :bar do
    do_something_that_can_throw_foo_or_bar
  end
end
Голый rescue эквивалентен rescue StandardError и является идиоматической конструкцией. "Голый catch", например catch() {throw :foo}, никогда ничего не поймает и не должен использоваться.