Eu tenho um código que precisa resgatar vários tipos de exceções em Ruby:
begin
a = rand
if a > 0.5
raise FooException
else
raise BarException
end
rescue FooException, BarException
puts "rescued!"
end
O que eu gostaria de fazer é de alguma forma armazenar a lista de tipos de exceção que desejo resgatar em algum lugar e passar esses tipos para a cláusula de resgate:
EXCEPTIONS = [FooException, BarException]
e depois:
rescue EXCEPTIONS
Isso é mesmo possível, e é possível sem algumas chamadas realmente hack-y para eval
? Não estou esperançoso, visto que estou vendo TypeError: class or module required for rescue clause
quando tento o acima.
Respostas:
Você pode usar uma matriz com o operador splat
*
.Se você for usar uma constante para a matriz como acima (com
EXCEPTIONS
), observe que você não pode defini-la dentro de uma definição, e também se você definir em alguma outra classe, você deve se referir a ela com seu namespace. Na verdade, não precisa ser uma constante.Operador Splat
O operador splat
*
"desempacota" uma matriz em sua posição para quesignifica o mesmo que
Você também pode usá-lo em um literal de array como
que é o mesmo que
ou em uma posição de argumento
que significa
[]
expande para vazio:Uma diferença entre o rubi 1.8 e o rubi 1.9 é com
nil
.Tenha cuidado com os objetos em que
to_a
está definido, comoto_a
será aplicado em tais casos:Com outros tipos de objetos, ele retorna a si mesmo.
fonte
EXCEPTIONS
neste caso? Gostaria de aprender um pouco mais.rescue InvalidRequestError, CardError => e
(consulte mikeferrier.com/2012/05/19/… )rescue *EXCEPTIONS => e
ondeEXCEPTIONS
é um array de nomes de classes de exceção.Embora a resposta dada por @sawa esteja tecnicamente correta, acho que ela usa mal o mecanismo de tratamento de exceções do Ruby.
Como o comentário de Peter Ehrlich sugere (apontando para um antigo post de blog de Mike Ferrier ), Ruby já está equipado com um mecanismo de tratamento de exceção DRY:
Usando essa técnica, podemos acessar o objeto de exceção, que geralmente contém algumas informações valiosas.
fonte
Acabei de encontrar esse problema e encontrei uma solução alternativa. No caso do seu
FooException
eBarException
serão todas classes de exceção personalizadas e, particularmente, se forem todas relacionadas de forma temática, você pode estruturar sua hierarquia de herança de forma que todas herdem da mesma classe pai e resgatem apenas a classe pai.Por exemplo, eu tinha três exceções:
FileNamesMissingError
,InputFileMissingError
eOutputDirectoryError
que eu queria resgate com um comunicado. Eu fiz outra classe de exceção chamadaFileLoadError
e, em seguida, configurei as três exceções acima para herdar dela. Eu então resgatei apenasFileLoadError
.Como isso:
fonte