How do I return early from a rake task?

2019-01-16 04:56发布

问题:

I have a rake task where I do some checks at the beginning, if one of the checks fails I would like to return early from the rake task, I don't want to execute any of the remaining code.

I thought the solution would be to place a return where I wanted to return from the code but I get the following error

unexpected return

回答1:

A Rake task is basically a block. A block, except lambdas, doesn't support return but you can skip to the next statement using next which in a rake task has the same effect of using return in a method.

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

Or you can move the code in a method and use return in the method.

task :foo do
  do_something
end

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

I prefer the second choice.



回答2:

You can use abort(message) from inside the task to abort that task with a message.



回答3:

I tend to use abort which is a better alternative in such situations, for example:

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


回答4:

If you need to break out of multiple block levels, you can use fail.

For example

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

(See https://stackoverflow.com/a/3753955/11543.)



回答5:

If you meant exiting from a rake task without causing the "rake aborted!" message to be printed, then you can use either "abort" or "exit". But "abort", when used in a rescue block, terminates the task as well as prints the whole error (even without using --trace). So "exit" is what I use.



回答6:

Return with an Error

If you're returning with an error (i.e. an exit code of 1) you'll want to use abort, which also takes an optional string param that will get outputted on exit:

task :check do
  errors = get_errors

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

  # Do remaining checks...
end

On the command line:

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

Return with Success

If you're returning without an error (i.e. an exit code of 0) you'll want to use exit, which does not take a string param.

task :check do
  errors = get_errors

  exit if errors.empty?

  # Process errors...
end

On the command line:

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

This is important if you're using this in a cron job or something that needs to do something afterwards based on whether the rake task was successful or not.



回答7:

I used next approach suggested by Simone Carletti, since when testing rake task, abort, which in fact is just a wrapper for exit, is not the desired behavior.

Example:

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


标签: ruby rake