关于ruby:如何从rake任务中提前返回?

How do I return early from a rake task?

我有一个rake任务,我在开始时做一些检查,如果其中一个检查失败,我想从rake任务中提前返回,我不想执行任何剩余的代码。

我认为解决方案是在我想要从代码返回的地方放置一个返回,但是我得到了以下错误

1
unexpected return

rake任务基本上是一个块。块(lambdas除外)不支持返回,但可以使用next跳到下一条语句,在rake任务中,该语句与在方法中使用返回具有相同的效果。

1
2
3
4
5
task :foo do
  puts"printed"
  next
  puts"never printed"
end

或者您可以在方法中移动代码并在方法中使用返回。

1
2
3
4
5
6
7
8
9
task :foo do
  do_something
end

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

我更喜欢第二种选择。


您可以从任务内部使用abort(message)以通过消息中止该任务。


我倾向于使用abort,在这种情况下,它是更好的选择,例如:

1
2
3
4
task :foo do
  something = false
  abort 'Failed to proceed' unless something
end


如果需要突破多个块级别,可以使用fail。

例如

1
2
3
4
5
6
task :something do
  [1,2,3].each do |i|
    ...
    fail"some error" if ...
  end
end

(请参阅https://stackoverflow.com/a/3753955/11543。)


如果您的意思是退出rake任务而不导致"rake中止!"要打印的消息,则可以使用"中止"或"退出"。但在救援块中使用"abort"时,会终止任务并打印整个错误(即使不使用--trace)。所以我用的是"出口"。


返回时出错?

如果返回时出现错误(即退出代码为1),则需要使用abort,它还需要一个可选的字符串参数,该参数将在退出时输出:

1
2
3
4
5
6
7
task :check do
  errors = get_errors

  abort("There are #{errors.count} errors!" ) if errors.any?

  # Do remaining checks...
end

在命令行上:

1
2
$ rake check && echo"All good"
#=> There are 2 errors!

成功归来?

如果返回时没有出现错误(即退出代码为0),则需要使用不带字符串参数的exit

1
2
3
4
5
6
7
task :check do
  errors = get_errors

  exit if errors.empty?

  # Process errors...
end

在命令行上:

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

如果您在cron作业中使用它,或者在以后需要根据rake任务是否成功来执行某些操作,那么这一点很重要。


我使用了Simone Carletti建议的next方法,因为在测试rake任务时,abort实际上只是exit的一个包装器,并不是期望的行为。

例子:

1
2
3
4
5
task auto_invoice: :environment do
  if Application.feature_disabled?(:auto_invoice)
    $stderr.puts 'Feature is disabled, aborting.'
  next
end