Wie komme ich früh von einer Rechenaufgabe zurück?

226

Ich habe eine Rake-Aufgabe, bei der ich zu Beginn einige Überprüfungen durchführe. Wenn eine der Überprüfungen fehlschlägt, möchte ich frühzeitig von der Rake-Aufgabe zurückkehren. Ich möchte keinen der verbleibenden Codes ausführen.

Ich dachte, die Lösung wäre, eine Rückgabe dort zu platzieren, wo ich vom Code zurückkehren wollte, aber ich erhalte den folgenden Fehler

unexpected return
Janak
quelle

Antworten:

285

Eine Rechenaufgabe ist im Grunde ein Block. Ein Block mit Ausnahme von Lambdas unterstützt keine Rückgabe, aber Sie können zur nächsten Anweisung springen, mit nextder in einer Rake-Task der gleiche Effekt wie bei der Verwendung von return in einer Methode erzielt wird.

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

Oder Sie können den Code in eine Methode verschieben und return in der Methode verwenden.

task :foo do
  do_something
end

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

Ich bevorzuge die zweite Wahl.

Simone Carletti
quelle
18
Ich mag auch den zweiten am liebsten. Je häufiger ich Rake verwende, desto mehr möchte ich nicht trivialen Code außerhalb der Aufgabendefinition halten. Keine 100% feste Regel, scheint aber eine gute Richtlinie zu sein, an der man arbeiten kann.
Mike Woodhouse
6
Ich habe es mit versucht breakund ich habe diesen Fehler: Rechen abgebrochen! Pause vom Prozessabschluss (Siehe vollständige Ablaufverfolgung durch Ausführen der Aufgabe mit --trace)
pupeno
4
Ich benutze lieber als nächstes. Warum sollten wir eine neue Methode deklarieren, um frühe Renditen zu unterstützen?
Derek Greer
5
Was tun Sie, wenn Sie tief in mehreren Blöcken verschachtelt sind? ( nextfunktioniert nur, wenn es auf "Ebene" des Blocks gibt, aus dem man ausbrechen kann.
mjs
3
Warnung: Das Deklarieren von Methoden in Rake-Tasks ist eine schlechte Idee, da sie für alle geladenen Rake-Tasks global sind, unabhängig vom Namespace. Next wird anstelle von break verwendet, da der Code im Block von jedem, der den Block ausführt, mehrmals aufgerufen werden kann (denken Sie an die .each-Methode).
Leslie Viljoen
181

Sie können diese abort(message)Aufgabe innerhalb der Aufgabe mit einer Nachricht abbrechen.

Sergikon
quelle
5
@ TylerRick Nein, es ist Kernel # Abbruch .
Jo Liss
10
Diese Methode eignet sich hervorragend zum Beenden in Situationen ohne Erfolg, da der Beendigungsstatus automatisch festgelegt wird.
Samuil
Dies ist ein Gewinner. Auch eine einfache Möglichkeit, Nutzungsrückmeldungen für Argumentfehler bereitzustellen.
David Hempy
Inline und viel erklärender als next. Liebe es.
SomeSchmo
22

Ich neige dazu zu verwenden, abortwas in solchen Situationen eine bessere Alternative ist, zum Beispiel:

task :foo do
  something = false
  abort 'Failed to proceed' unless something
end
khelll
quelle
1
Aber wie geht es Ihnen, abortohne mit einem 1Exit-Code zu beenden? Rechenaufgaben werden häufig in der Befehlszeile verwendet, um Erfolg oder Misserfolg zu bestimmen. Gibt es eine "erfolgreiche" abort?
Joshua Pinter
2
Beantwortete meine eigenen Fragen: Sieht so aus, exitals wäre dies ein guter Weg, um erfolgreich zu beenden.
Joshua Pinter
18

Rückkehr mit einem Fehler ❌

Wenn Sie mit einem Fehler (dh einem Exit-Code von 1) zurückkehren, den Sie verwenden möchten, abortwird auch ein optionaler Zeichenfolgenparameter verwendet, der beim Beenden ausgegeben wird:

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

In der Befehlszeile:

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

Rückkehr mit Erfolg ✅

Wenn Sie ohne Fehler (dh mit einem Exit-Code von 0) zurückkehren, möchten Sie Folgendes verwenden exit, für das kein Zeichenfolgenparameter erforderlich ist.

task :check do

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

end

In der Befehlszeile:

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

Dies ist wichtig, wenn Sie dies in einem Cron-Job verwenden oder etwas, das anschließend ausgeführt werden muss, je nachdem, ob die Rechenaufgabe erfolgreich war oder nicht.

Joshua Pinter
quelle
8

Wenn Sie vorhatten, eine Rechenaufgabe zu verlassen, ohne den "Rechen abgebrochen!" Wenn die Nachricht gedruckt werden soll, können Sie entweder "Abbrechen" oder "Beenden" verwenden. "Abbruch" beendet jedoch bei Verwendung in einem Rettungsblock die Aufgabe und gibt den gesamten Fehler aus (auch ohne Verwendung von --trace). Also benutze ich "exit".

ZX12R
quelle
3
Im Allgemeinen halte ich die Verwendung von "exit" anstelle von return / break für eine schlechte Idee, da sie nicht nur aus dem aktuellen proc / method / etc. Herausspringt . - Es beendet den gesamten Prozess und überspringt jeglichen Code, den die Aufrufermethode möglicherweise später ausführen soll (einschließlich möglicherweise einer Bereinigung). Aber für eine Rechenaufgabe ist es wahrscheinlich kein Problem ...
Tyler Rick
0

Ich habe nextden von Simone Carletti vorgeschlagenen Ansatz verwendet , da beim Testen der Rechenaufgabe abort, die eigentlich nur ein Wrapper exitist, nicht das gewünschte Verhalten vorliegt.

Beispiel:

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