jobs.each do |job|
msg job.name do
break if stop_all_jobs?
job.run!
end
end
def msg(msg, &block)
puts 'START ' + msg
yield
puts 'END ' + msg
end
In the above example break
does not break out of the loop as expected. It only breaks out of the msg
code block.
This seems a little odd, but I guess it is based on context, that said, how do I break out of the loop from code which is within a yield
ed code block?
One way is to use throw/catch
. No, not exceptions, Ruby has a separate control-of-flow feature that works a bit like exceptions, without all the overhead (although I must admit I'm not sure that there isn't any overhead in using it):
catch :stop_all_jobs do
msg job.name do
throw :stop_all_jobs if stop_all_jobs?
job.run!
end
end
You can even pass a value as the second argument to throw
which will be the result of the catch
block.
A potentially more readable solution would, of course, be to pack the code up in a method and use return
in place of break
. But that wouldn't be as fun.