Sometimes it makes sense to treat errors as part of an application's "valid" flow of events. Meaning, expected errors should not necessarily make your code go crazy when random errors are raised.
With that in mind, I created a way to implement some kind of "Result Object" by rescuing StandardError instances and handling these errors gracefully.
class Gracefully class << self alias_method :handle, :new end attr_reader :error, :value def initialize @value = nil @error = nil begin @value = yield rescue => e @error = e end end def success? error.nil? end def on_success return self unless success? result = yield(@value) return result if result.is_a?(Gracefully) Gracefully.handle { result } end def on_failure return self if success? result = yield(@error) return result if result.is_a?(Gracefully) Gracefully.handle { result } end end
In short, _ Gracefully _ is a wrapper for a result object– it’s either a success value or an error object.
result = Gracefully.handle { Order.find 999 }
In the example above, if order with id 999 does not exist, result.success? method will return false. Otherwise, true.
If result.success?is true, result.value will contain the successful value. Otherwise, result.error will hold the error object itself.
Whenever Gracefully.handle is called, it will return a Gracefully object. If you want to get the raw value, you can use result.value.
More Usage
result = Gracefully.handle { ComplicatedService.new(foo, bar).process } if result.success? # do success stuff use_value(result.value) else # do failure stuff log_error(result.error) end
Chaining Usage
Gracefully.handle { SomeComplicatedService.new.call }.on_success do |val| val.update!(column_name: 'stuff') end Gracefully.handle { SomeComplicatedService.new.call }.on_failure do |e| do_whatever_you_wish_with_the_error(e) end
By using this, I can be resilient in handling errors and be able to recover from failures in the process flow.
The post Handling Errors Gracefully appeared first on KatPadi's Point.
--
Visit my website @ http://katpadi.ph.
Top comments (0)