如何从rake任务中提前返回?

Jan*_*nak 213 ruby rake

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

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

unexpected return
Run Code Online (Sandbox Code Playgroud)

Sim*_*tti 272

Rake任务基本上是一个块.除lambda之外的块不支持返回,但是您可以跳到下一个语句,使用nextrake任务在方法中使用return具有相同的效果.

task :foo do
  puts "printed"
  next
  puts "never printed"
end
Run Code Online (Sandbox Code Playgroud)

或者您可以在方法中移动代码并在方法中使用return.

task :foo do
  do_something
end

def do_something
  puts "startd"
  return
  puts "end"
end
Run Code Online (Sandbox Code Playgroud)

我更喜欢第二种选择.

  • 我也喜欢第二个.我使用rake越多,我就越喜欢将非平凡代码保留在任务定义之外.不是100%坚定的规则,但似乎是一个很好的指导方针. (18认同)
  • 我试过'break`并且我遇到了这个错误:rake aborted!从proc-closure中断(通过使用--trace运行任务来查看完整跟踪) (6认同)
  • 如果你被深深地嵌套在多个街区里,你会怎么做?(`next`只有在块的"级别"突破时才有效. (5认同)
  • 我更喜欢使用下一个.我们为什么要宣布一种新的方法来支持早期的回报呢? (3认同)
  • @LeslieViljoen 所说的我再怎么强调也不为过。在你的 rake 文件中声明 `do_something` 方法意味着它会污染 _all_ 其他 rake 文件。rake 文件中没有“私有”方法。因此,如果您有另一个也定义了 `do_something` 的 rake 文件,您将发生碰撞,但更糟糕的是,它们将无声地碰撞,您会发现自己在不知情的情况下运行完全不同的方法。非常危险。 (3认同)
  • 第二种解决方案更好.在你的第一个解决方案中,我宁愿使用break而不是next来摆脱障碍...也应该工作,不应该吗? (2认同)
  • 警告:在Rake任务中声明方法是个坏主意,因为它们对于所有加载的Rake任务都是全局的,与命名空间无关.使用Next而不是break,因为块中的代码可能被执行块的任何事件多次调用(想想.each方法). (2认同)

小智 171

您可以abort(message)在任务内部使用该消息中止该任务.

  • 这种方式对于退出非成功情况是优越的,因为它自动设置退出状态. (8认同)
  • @TylerRick不,它是[Kernel#abort](http://www.ruby-doc.org/core-1.9.3/Kernel.html#method-i-abort). (5认同)

khe*_*lll 20

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

task :foo do
  something = false
  abort 'Failed to proceed' unless something
end
Run Code Online (Sandbox Code Playgroud)

  • 回答了我自己的问题:看来“退出”是成功退出的好方法。 (2认同)

mjs*_*mjs 11

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

例如

task :something do
  [1,2,3].each do |i|
    ...
    fail "some error" if ...
  end
end
Run Code Online (Sandbox Code Playgroud)

(参见/sf/answers/262776881/.)


Jos*_*ter 10

返回错误?

如果你正在返回错误(即退出代码1),你要使用abort,这也需要一个可选的字符串PARAM,将获得在退出输出:

task :check do
  errors = get_errors

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

  # Do remaining checks...
end
Run Code Online (Sandbox Code Playgroud)

在命令行上:

$ rake check && echo "All good"
#=> There are 2 errors!
Run Code Online (Sandbox Code Playgroud)

成功返回?

如果您返回的消息没有错误(即退出代码为0),则需要使用exit,而该参数不需要字符串参数。

task :check do
  errors = get_errors

  exit if errors.empty?

  # Process errors...
end
Run Code Online (Sandbox Code Playgroud)

在命令行上:

$ rake check && echo "All good"
#=> All good
Run Code Online (Sandbox Code Playgroud)

如果您要在cron作业中使用此功能,或者需要根据rake任务是否成功进行事后处理,则这一点很重要。

  • 不,不应该。这不仅会让您脱离任务,还会使您脱离整个堆栈,从而终止调用它的整个进程。如果您内联调用它们,这将使您的应用程序崩溃,或者在为它们编写测试时给出误报。使用“next”是唯一“正确”的方法。 (2认同)

ZX1*_*12R 8

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

  • 通常,我认为使用“退出”而不是返回/中断是一个坏主意,因为它不仅会跳出* current * proc / method / etc。-它退出了整个过程,并跳过了调用方方法可能打算在此后运行的任何代码(可能包括一些清理工作)。但是对于耙任务,我想这可能不是问题... (3认同)