Как мне рано вернуться с грабли?


226

У меня есть задача rake, в которой я делаю некоторые проверки в начале, если одна из проверок не удалась, я хотел бы вернуться рано из задачи rake, я не хочу выполнять какой-либо оставшийся код.

Я думал, что решение было бы разместить возврат, где я хотел бы вернуться из кода, но я получаю следующую ошибку

unexpected return

Ответы:


285

Задача Rake - это в основном блок. Блок, кроме лямбда-выражений, не поддерживает return, но вы можете перейти к следующему оператору, используя nextкоторый в задаче rake, тот же эффект, что и при использовании return в методе.

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

Или вы можете переместить код в метод и использовать return в методе.

task :foo do
  do_something
end

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

Я предпочитаю второй выбор.


18
Мне тоже больше нравится второй. Чем больше я использую rake, тем больше мне нравится хранить нетривиальный код вне определения задачи. Не на 100% твердое правило, но кажется хорошим руководством для работы.
Майк Вудхаус

6
Я пытался с, breakи у меня есть эта ошибка: грабли прерваны! перерыв от PROC-закрытия (Полный след, выполнив задачу с --trace)
pupeno

4
Я предпочитаю использовать следующий. Почему мы должны объявлять новый метод только для поддержки раннего возврата?
Дерек Грир

5
Что вы делаете, если вы глубоко вложены в несколько блоков? ( nextработает, только если на «уровне» блока вырваться наружу.
mjs

3
Предупреждение: объявление методов в задачах Rake - плохая идея, потому что они глобальны для всех загруженных задач Rake и не имеют отношения к пространству имен. Далее используется вместо break, потому что код в блоке может вызываться несколько раз, независимо от того, что выполняет блок (вспомним метод .each).
Лесли Вильджоен

181

Вы можете использовать abort(message)внутри задачи, чтобы отменить эту задачу с сообщением.


5
@TylerRick Нет, это Kernel # abort .
Джо Лисс

10
Этот способ лучше подходит для выхода в неуспешных ситуациях, поскольку он автоматически устанавливает состояние выхода.
Самуил

Это победитель. Также простой способ обеспечить обратную связь использования для ошибок аргумента.
Дэвид Хэмпи

Встроенный и гораздо более понятный, чем next. Любить это.
SomeSchmo

22

Я склонен использовать, abortкоторая является лучшей альтернативой в таких ситуациях, например:

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

1
Но как вы abortбез выхода с 1кодом выхода? Rake-задачи часто используются в командной строке для определения успеха или неудачи. Есть ли «успешный» abort?
Джошуа Пинтер

2
Ответил на мои собственные вопросы: похоже, exitэто хороший способ успешно выйти.
Джошуа Пинтер

19

Вернуться с ошибкой ❌

Если вы возвращаетесь с ошибкой (то есть с кодом выхода 1), которую вы захотите использовать abort, она также принимает необязательный строковый параметр, который будет выведен при выходе:

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

В командной строке:

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

Возвращайся с успехом ✅

Если вы возвращаетесь без ошибки (то есть кода выхода 0), вы захотите использовать его exit, который не принимает строковый параметр.

task :check do

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

end

В командной строке:

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

Это важно, если вы используете это в задании cron или в чем-то, что впоследствии должно быть выполнено в зависимости от того, была ли успешна задача rake или нет.



8

Если вы имели в виду выход из задачи по рейку, не вызывая "рейк отменен!" сообщение, которое будет напечатано, тогда вы можете использовать «abort» или «exit». Но «abort», когда используется в блоке восстановления, завершает задачу, а также печатает всю ошибку (даже без использования --trace). Так что «выход» - это то, что я использую.


3
В общем, я думаю, что использовать «выход» вместо return / break - плохая идея, поскольку он не просто выпрыгивает из текущего proc / method / etc. - он завершает весь процесс и пропускает любой код, который, возможно, метод вызывающей стороны должен был запустить впоследствии (включая, возможно, некоторую очистку). Но для граблей, я думаю, это, вероятно, не проблема ...
Тайлер Рик

0

Я использовал nextподход, предложенный Симон Карлетти, так как при тестировании рейка задача, abortкоторая на самом деле является просто оберткой exit, не соответствует желаемому поведению.

Пример:

task auto_invoice: :environment do
  if Application.feature_disabled?(:auto_invoice)
    $stderr.puts 'Feature is disabled, aborting.'
  next
end
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.