¿Cómo regreso temprano de una tarea de rastrillo?

226

Tengo una tarea de rastrillo donde hago algunas verificaciones al principio, si una de las verificaciones falla, me gustaría regresar temprano de la tarea de rastrillo, no quiero ejecutar ninguno de los códigos restantes.

Pensé que la solución sería colocar un retorno donde quería regresar del código, pero recibo el siguiente error

unexpected return
Janak
fuente

Respuestas:

285

Una tarea de rastrillo es básicamente un bloque. Un bloque, excepto lambdas, no admite el retorno, pero puede pasar a la siguiente instrucción nextque utiliza en una tarea de rastrillo el mismo efecto que usar el retorno en un método.

task :foo do
  puts "printed"
  next
  puts "never printed"
end

O puede mover el código en un método y usar return en el método.

task :foo do
  do_something
end

def do_something
  puts "startd"
  return
  puts "end"
end

Prefiero la segunda opción.

Simone Carletti
fuente
18
También me gusta el segundo. Cuanto más uso el rastrillo, más me gusta mantener el código no trivial fuera de la definición de la tarea. No es una regla 100% firme, pero parece ser una buena guía para trabajar.
Mike Woodhouse
66
Lo he intentado breaky tengo este error: ¡rastrillo abortado! romper el proceso de cierre (Ver seguimiento completo ejecutando la tarea con --trace)
pupeno
44
Prefiero usar el siguiente. ¿Por qué deberíamos declarar un nuevo método solo para respaldar los retornos tempranos?
Derek Greer
55
¿Qué haces si estás profundamente anidado en varios bloques? ( nextsolo funciona si hay un "nivel" de bloque para salir.
mjs
3
Advertencia: declarar métodos en las tareas de Rake es una mala idea porque son globales para todas las tareas de Rake cargadas, sin importar el espacio de nombres. Luego se usa en lugar de break porque el código en el bloque puede ser llamado varias veces por lo que sea que esté ejecutando el bloque (piense en el método .each).
Leslie Viljoen
181

Puede usar abort(message)desde dentro de la tarea para anular esa tarea con un mensaje.

Sergikon
fuente
55
@TylerRick No, es Kernel # abort .
Jo Liss
10
Esta manera es superior para salir en situaciones sin éxito, ya que establece automáticamente el estado de salida.
samuil
Este es un ganador. También es una manera fácil de proporcionar comentarios de uso para errores de argumento.
David Hempy
En línea y mucho más explicativo que next. Quiéralo.
SomeSchmo
22

Tiendo a usar abortcuál es una mejor alternativa en tales situaciones, por ejemplo:

task :foo do
  something = false
  abort 'Failed to proceed' unless something
end
khelll
fuente
1
Pero, ¿cómo abortsin salir con un 1código de salida? Las tareas de rastrillo a menudo se usan en la línea de comando para determinar el éxito o el fracaso. ¿Hay un "exitoso" abort?
Joshua Pinter
2
Respondí mis propias preguntas: parece que exites una buena manera de salir con éxito.
Joshua Pinter
19

Regrese con un error ❌

Si regresa con un error (es decir, un código de salida de 1) que querrá usar abort, que también toma un parámetro de cadena opcional que se generará en la salida:

task :check do

  # If any of your checks fail, you can exit early like this.
  abort( "One of the checks has failed!" ) if check_failed?

end

En la línea de comando:

$ rake check && echo "All good"
#=> One of the checks has failed!

Regrese con éxito ✅

Si regresa sin un error (es decir, un código de salida de 0), querrá usarlo exit, lo que no requiere un parámetro de cadena.

task :check do

  # If any of your checks fail, you can exit early like this.
  exit if check_failed?

end

En la línea de comando:

$ rake check && echo "All good"
#=> All good

Esto es importante si está usando esto en un trabajo cron o algo que necesita hacer algo después en función de si la tarea de rake fue exitosa o no.

Joshua Pinter
fuente
8

Si quisiste salir de una tarea de rastrillo sin causar el "rastrillo abortado". mensaje a imprimir, entonces puede usar "abortar" o "salir". Pero "abortar", cuando se usa en un bloque de rescate, finaliza la tarea e imprime todo el error (incluso sin usar --trace). Entonces "salir" es lo que uso.

ZX12R
fuente
3
En general, creo que usar "exit" en lugar de return / break es una mala idea, ya que no solo salta del proceso / método / etc actual . - sale de todo el proceso y omite cualquier código que el método de la persona que llama haya tenido la intención de ejecutar después (incluyendo posiblemente alguna limpieza). Pero para una tarea de rastrillo, supongo que probablemente no sea un problema ...
Tyler Rick
0

Utilicé el nextenfoque sugerido por Simone Carletti, ya que al probar la tarea de rastrillo abort, que de hecho es solo una envoltura exit, no es el comportamiento deseado.

Ejemplo:

task auto_invoice: :environment do
  if Application.feature_disabled?(:auto_invoice)
    $stderr.puts 'Feature is disabled, aborting.'
  next
end
Artur Beljajev
fuente