As programmers we usually select our preferred tools, our preferred language, IDE, code editor, …
For the last years, my favorite programming language is Ruby, not only because of Rails (but of course it has something to do with it), but because the language is powerful and flexible, and as such has many details that most Ruby programmers do not remember in the daily usage of the language.
And as strange as it appears, basic flow control keywords are usually forgotten.
And these keywords, when well used, can make your code a lot cleaner.
Let’s see some examples of how to use these keywords bellow:
retry
The ‘retry’ keyword is used in a begin/rescue block, when you want to re-run the block, it only works inside an exception handling block.
It can be used for example, to retry a failed remote service call:
count = 0 begin remote_service.call rescue count = count + 1 retry if count >= 3 end
I’ve seen a lot of uglier versions of this code, even nested begin/rescue blocks to call the service more than once. Or loops with a begin/rescue block inside, and all they needed to know to improve the code was the “retry” keyword.
redo
The redo keyword is very similar, but it works in loops, every time you want to re execute that loop in the same iteration, for example, if you are looping through a list of commands, and want to retry each command until they finished successfully, you could use a code like this:
[command_1, command_2, command_3, command_4].each do |command| command.execute redo unless command.success? end
With this code, you’ll run the execute method of the same command, until that command executes successfully, it is similar to this loop:
[command_1, command_2, command_3, command_4].each do |command| loop do command.execute break if command.success? end end
Bonus: did you know about the “loop” keyword? it is like an eternal enumerator
next
The next keyword works inside loops too, but instead of repeating the same iteration, it jumps from that point to the next iteration, ignoring the code after the call to ‘next’.
For example, you could be iterating a similar command list, but some of the commands do not apply to the current user, your loop would be like this:
[command_1, command_2, command_3, command_4].each do |command| command.load_params_from_file next unless @user.should_run(command) puts "Running #{command.name}" command.execute command.save_results @user.log_command_execution end