with standard rails error begin ruby exception rescue

standard - Pasar múltiples clases de error a la cláusula de rescate de ruby de manera SECA



ruby exception backtrace (2)

Tengo un código que necesita rescatar varios tipos de excepciones en ruby:

begin a = rand if a > 0.5 raise FooException else raise BarException end rescue FooException, BarException puts "rescued!" end

Lo que me gustaría hacer es de alguna manera almacenar la lista de tipos de excepciones que quiero rescatar en algún lugar y pasar esos tipos a la cláusula de rescate:

EXCEPTIONS = [FooException, BarException]

y entonces:

rescue EXCEPTIONS

¿Es esto posible, y es posible sin algunas llamadas realmente hack-y a eval ? No tengo esperanzas dado que estoy viendo TypeError: class or module required for rescue clause cuando intento lo anterior.


Me encontré con este problema y encontré una solución alternativa. En el caso de que su FooException y BarException sean todas clases de excepciones personalizadas y particularmente si están relacionadas temáticamente, puede estructurar su jerarquía de herencia de modo que todas ellas hereden de la misma clase primaria y luego rescaten solo la clase principal.

Por ejemplo, tenía tres excepciones: FileNamesMissingError , InputFileMissingError y OutputDirectoryError que quería rescatar con una declaración. Hice otra clase de excepción llamada FileLoadError y luego configuré las tres excepciones anteriores para heredar de ella. Luego rescaté solo FileLoadError .

Me gusta esto:

class FileLoadError < StandardError end class FileNamesMissingError < FileLoadError end class InputFileMissingError < FileLoadError end class OutputDirectoryError < FileLoadError end [FileNamesMissingError, InputFileMissingError, OutputDirectoryError].each do |error| begin raise error rescue FileLoadError => e puts "Rescuing #{e.class}." end end


Puede usar una matriz con el operador splat * .

EXCEPTIONS = [FooException, BarException] begin a = rand if a > 0.5 raise FooException else raise BarException end rescue *EXCEPTIONS puts "rescued!" end

Si va a usar una constante para la matriz como se indica arriba (con EXCEPTIONS ), tenga en cuenta que no puede definirla dentro de una definición, y también si la define en alguna otra clase, debe referirse a ella con su espacio de nombres. En realidad, no tiene que ser una constante.

Operador Splat

El operador splat * "desempaqueta" una matriz en su posición para que

rescue *EXCEPTIONS

significa lo mismo que

rescue FooException, BarException

También puede usarlo dentro de una matriz literal como

[BazException, *EXCEPTIONS, BangExcepion]

que es lo mismo que

[BazException, FooException, BarException, BangExcepion]

o en una posición de discusión

method(BazException, *EXCEPTIONS, BangExcepion)

lo que significa

method(BazException, FooException, BarException, BangExcepion)

[] expande a vacío

[a, *[], b] # => [a, b]

Una diferencia entre ruby ​​1.8 y ruby ​​1.9 es nil .

[a, *nil, b] # => [a, b] (ruby 1.9) [a, *nil, b] # => [a, nil, b] (ruby 1.8)

Tenga cuidado con los objetos en los que se define to_a , ya que se aplicará to_a en tales casos:

[a, *{k: :v}, b] # => [a, [:k, :v], b]

Con otros tipos de objetos, se devuelve a sí mismo.

[1, *2, 3] # => [1, 2, 3]