ruby - route - standard error rails
Excepciones de Ruby-¿Por qué “más”? (5)
Aquí hay un caso de uso concreto para else
en una expresión de begin
. Supongamos que está escribiendo pruebas automatizadas y desea escribir un método que devuelva el error generado por un bloque. Pero también desea que la prueba falle si el bloque no genera un error. Puedes hacerlo:
def get_error_from(&block)
begin
block.call
rescue => err
err # we want to return this
else
raise "No error was raised"
end
end
Tenga en cuenta que no puede mover la raise
dentro del bloque de begin
, porque se recuperará d. Por supuesto, hay otras formas sin usar else
, como verificar si err
es nil
después del end
, pero eso no es tan sucinto.
Personalmente, rara vez uso else
de esta manera porque creo que rara vez se necesita, pero resulta útil en esos casos raros.
EDITAR
Se me ocurrió otro caso de uso. Aquí hay un begin
/ rescue
típico:
begin
do_something_that_may_raise_argument_error
do_something_else_when_the_previous_line_doesnt_raise
rescue ArgumentError => e
handle_the_error
end
¿Por qué esto es menos que ideal? Debido a que la intención es rescue
cuando do_something_that_may_raise_argument_error
genera ArgumentError
, no cuando do_something_else_when_the_previous_line_doesnt_raise
aumenta.
Por lo general, es mejor usar begin
/ rescue
para ajustar el código mínimo que desea proteger de un raise
, porque de lo contrario:
- Puede enmascarar errores en el código que no se suponía que debía
raise
- La intención del
rescue
es más difícil de descifrar. Alguien (incluido tu yo futuro) puede leer el código y preguntarse "¿Qué expresión quería proteger? Se parece a la expresión ABC ... pero tal vez la expresión DEF también? ¿Qué pretendía el autor?" La refactorización se vuelve mucho más difícil.
Evitas esos problemas con este simple cambio:
begin
do_something_that_may_raise_argument_error
rescue ArgumentError => e
handle_the_error
else
do_something_else_when_the_previous_line_doesnt_raise
end
Estoy tratando de entender las excepciones en Ruby pero estoy un poco confundido. El tutorial que estoy usando dice que si se produce una excepción que no coincide con ninguna de las excepciones identificadas por las declaraciones de rescate, puede usar un "más" para capturarlo:
begin
# -
rescue OneTypeOfException
# -
rescue AnotherTypeOfException
# -
else
# Other exceptions
ensure
# Always will be executed
end
Sin embargo, también vi más adelante en el tutorial "rescate" que se usó sin una excepción especificada:
begin
file = open("/unexistant_file")
if file
puts "File opened successfully"
end
rescue
file = STDIN
end
print file, "==", STDIN, "/n"
Si puedes hacer esto, ¿entonces necesito usar alguna otra cosa? ¿O puedo simplemente usar un rescate genérico al final como este?
begin
# -
rescue OneTypeOfException
# -
rescue AnotherTypeOfException
# -
rescue
# Other exceptions
ensure
# Always will be executed
end
El bloque else
en un bloque final de rescate de inicio se usa cuando quizás espera que ocurra una excepción de algún tipo. Si ejecuta todas las excepciones esperadas pero aún no ha generado nada, entonces en su bloque else puede hacer lo que sea necesario ahora que sabe que su código original no tuvo errores.
Gracias a else
a veces puede fusionar dos bloques begin end
anidados.
Entonces (ejemplo simplificado de mi código actual) en lugar de:
begin
html = begin
NetHTTPUtils.request_data url
rescue NetHTTPUtils::Error => e
raise unless 503 == e.code
sleep 60
retry
end
redo unless html["market"]
end
usted escribe:
begin
html = NetHTTPUtils.request_data url
rescue NetHTTPUtils::Error => e
raise unless 503 == e.code
sleep 60
retry
else
redo unless html["market"]
end
La única razón por la que puedo ver el bloque else
es si desea ejecutar algo antes del bloque ensure
cuando el código en el bloque de begin
no generó ningún error.
begin
puts "Hello"
rescue
puts "Error"
else
puts "Success"
ensure
puts "my old friend"
puts "I''ve come to talk with you again."
end
La else
es para cuando el bloque se completa sin una excepción lanzada. El ensure
se ejecuta si el bloque se completa con éxito o no. Ejemplo:
begin
puts "Hello, world!"
rescue
puts "rescue"
else
puts "else"
ensure
puts "ensure"
end
Esto imprimirá Hello, world!
, luego else
, entonces ensure
.