Consider the following minimal example:
class SomeException < StandardError
end
class Example
@@logger = Logger.new
@@failure_count = 0
def do_a_thing(array)
raise SomeException unless array.some_check?
# more random code
end
def some_long_process(array)
array.each do |item|
begin
do_a_thing(item)
do_something_else(item)
do_yet_another_thing(item)
rescue SomeException
@@logger.error 'Process failed'
@@failure_count += 1
next
end
end
@@logger.info("Process done, #{@@failure_count} failures")
end
The reason I've structured the code in this way is that this class's main job is to iterate through an array of hashes. If the do_a_thing
task fails, I need it to log that failure, do some cleanup, and then skip the remainder of the steps in that begin
block. Every possible failure in those steps is signaled by raising SomeException
.
However, I'm aware that using exceptions for flow control is generally discouraged. My reasons for doing it here are:
The library (Mechanize) used in the various do_thing steps will automatically throw an exception if it gets a bogus HTML return back, which lends itself well to the logical organization of this class.
I want to count the errors on stdout, as this is part of a gem that will be used to do automated work.
I want to keep the logging for step failures in those methods if possible due to the large variety of possible failures, and use the external
.each
loop only for bookkeeping.
I want to know if there is a clearer/more idiomatic/fewer lines of code way to accomplish this same task. Is this the right way to be using exceptions?
throw
/catch
. If this is needed at all, Rubyists prefer those over exceptions for control flow.