Jak wrócić wcześniej z zadania prowizji?


226

Mam zadanie prowizji, w którym na początku przeprowadzam kilka kontroli, jeśli jeden z testów nie powiedzie się, chciałbym wrócić wcześniej z zadania prowizji, nie chcę wykonywać żadnego z pozostałych kodów.

Myślałem, że rozwiązaniem byłoby umieszczenie zwrotu w miejscu, w którym chciałbym powrócić z kodu, ale pojawia się następujący błąd

unexpected return

Odpowiedzi:


285

Zadanie prowizji jest w zasadzie blokiem. Blok, z wyjątkiem lambdas, nie obsługuje return, ale możesz przejść do następnej instrukcji, używając nextktórej w zadaniu rake ma taki sam efekt jak return w metodzie.

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

Lub możesz przenieść kod w metodzie i użyć return w metodzie.

task :foo do
  do_something
end

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

Wolę drugi wybór.


18
Drugi też najbardziej mi się podoba. Im częściej używam prowizji, tym bardziej lubię trzymać nietrywialny kod poza definicją zadania. Nie jest to w 100% twarda zasada, ale wydaje się być dobrą wskazówką do pracy.
Mike Woodhouse

6
Próbowałem breaki mam ten błąd: rake przerwany! przerwa od proc-closure (Zobacz pełny ślad, uruchamiając zadanie za pomocą --trace)
pupeno

4
Wolę używać dalej. Dlaczego powinniśmy zadeklarować nową metodę, która ma wspierać wczesne powroty?
Derek Greer,

5
Co robisz, jeśli jesteś głęboko zagnieżdżony w wielu blokach? ( nextdziała tylko wtedy, gdy jest na „poziomie” bloku do wyrwania.
mjs 30.01.2013

3
Ostrzeżenie: deklarowanie metod w zadaniach prowizji jest złym pomysłem, ponieważ są one globalne dla wszystkich załadowanych zadań prowizji, bez względu na przestrzeń nazw. Zamiast break stosuje się Next, ponieważ kod w bloku może być wywoływany wielokrotnie przez to, co wykonuje blok (pomyśl o metodzie .each).
Leslie Viljoen

181

Możesz użyć abort(message)z wnętrza zadania, aby przerwać to zadanie za pomocą wiadomości.


5
@TylerRick Nie, to Kernel # przerywa .
Jo Liss,

10
Ten sposób jest lepszy do wychodzenia w sytuacjach nieudanych, ponieważ automatycznie ustawia status wyjścia.
samuil

To jest zwycięzca. Również łatwy sposób na dostarczenie informacji zwrotnej na temat błędów argumentów.
David Hempy,

Wbudowany i znacznie bardziej objaśniający niż next. Kocham to.
SomeSchmo

22

Zwykle używam, abortktóra jest lepszą alternatywą w takich sytuacjach, na przykład:

task :foo do
  something = false
  abort 'Failed to proceed' unless something
end

1
Ale jak sobie abortradzisz bez wychodzenia z 1kodem wyjścia? Zadania prowizji są często używane w wierszu polecenia do określenia sukcesu lub niepowodzenia. Czy istnieje „sukces” abort?
Joshua Pinter,

2
Odpowiedziałem na własne pytania: wygląda na exitto, że to dobry sposób na pomyślne wyjście.
Joshua Pinter,

19

Wróć z błędem ❌

Jeśli wracasz z błędem (tj. Kod zakończenia 1), którego chcesz użyć abort, który również przyjmuje opcjonalny parametr ciągu, który zostanie wyświetlony na wyjściu:

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

W wierszu poleceń:

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

Wróć z sukcesem ✅

Jeśli wracasz bez błędu (tj. Kod wyjścia z 0), będziesz chciał użyć exit, który nie przyjmuje parametrów ciągu.

task :check do

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

end

W wierszu poleceń:

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

Jest to ważne, jeśli używasz tego do zadania cron lub czegoś, co musi zrobić później, w zależności od tego, czy zadanie rake zakończyło się powodzeniem, czy nie.



8

Jeśli miałeś na myśli wyjście z zadania rake bez powodowania „przerwania rake!” wiadomość do wydrukowania, możesz użyć „Przerwij” lub „Wyjdź”. Ale „przerywanie”, gdy jest używane w bloku ratunkowym, kończy zadanie, a także drukuje cały błąd (nawet bez użycia --trace). Używam więc „exit”.


3
Ogólnie myślę, że użycie „exit” zamiast return / break jest złym pomysłem, ponieważ nie wyskakuje ono z bieżącej procedury / metody / etc. - wychodzi z całego procesu i pomija kod, który metoda wywołująca mogła następnie uruchomić (łącznie z ewentualnym czyszczeniem). Ale w przypadku zadania rake chyba nie jest to problem ...
Tyler Rick

0

Użyłem nextpodejścia sugerowanego przez Simone Carletti, ponieważ podczas testowania zadania rake abort, które w rzeczywistości jest tylko opakowaniemexit , nie jest pożądane zachowanie.

Przykład:

task auto_invoice: :environment do
  if Application.feature_disabled?(:auto_invoice)
    $stderr.puts 'Feature is disabled, aborting.'
  next
end
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.