Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I return early from a rake task?

Tags:

ruby

rake

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.


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


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
  
  # If any of your checks fail, you can exit early like this.
  abort( "One of the checks has failed!" ) if check_failed?

end

On the command line:

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

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
  
  # If any of your checks fail, you can exit early like this.
  exit if check_failed?
  
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.


Bonus: Return with an Error from a rescue block without the stacktrace.

By default, if you use abort inside of a rescue block, it will output the entire stack trace, even if you just use abort without re-raising the error.

To get around this, you can supply a non-zero exit code to the exit command, like:


task :check do

  begin
    do_the_thing_that_raises_an_exception
  rescue => error
    puts error.message
 
    exit( 1 )
  end

end

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