lib/convenient_service/exception.rb in convenient_service-0.16.0 vs lib/convenient_service/exception.rb in convenient_service-0.17.0

- old
+ new

@@ -1,16 +1,104 @@ # frozen_string_literal: true -## -# Base class for all `ConvenientService` exceptions. -# Can be used as a catch-all solution, for example: -# -# begin -# any_service.result -# rescue ConvenientService::Exception => exception -# puts exception.message -# end -# module ConvenientService + ## + # Base class for all `ConvenientService` exceptions. + # + # @example Can be used as a catch-all solution. + # + # begin + # any_service.result + # rescue ConvenientService::Exception => exception + # puts exception.message + # end + # class Exception < ::StandardError + class << self + ## + # Creates `ConvenientService` exception instance. + # In contract to `StandardError.new`, may accept `kwargs`. + # In such a case the descendant must implement `initialize_with_kwargs` to specify the logic of how to generate a `message`. + # Without arguments behavior is also changed, it calls `initialize_without_arguments` instead of immediately setting `nil` as `message`. + # + # @note `initialize_with_kwargs` or `initialize_without_arguments` must call `initialize(message)`, otherwise exception instance won't be properly set up. + # + # @overload new + # Calls `initialize_without_arguments` under the hood to generate the exception message. + # + # @api private + # + # @return [ConvenientService::Exception] + # + # @example Usage. + # module Exceptions + # class Foo < ::ConvenientService::Exception + # def initialize_without_arguments + # # message = ... + # initialize(message) + # end + # end + # end + # + # ::ConvenientService.raise Foo.new + # + # @overload new(message) + # Calls `initialize(message)` under the hood to set the exception message. + # + # @api private + # + # @param message [String] + # + # @return [ConvenientService::Exception] + # + # @example Usage. + # module Exceptions + # class Foo < ::ConvenientService::Exception + # end + # end + # + # ::ConvenientService.raise Foo.new("some message") + # + # @overload new(**kwargs) + # Calls `initialize_with_kwargs(**kwargs)` under the hood to generate the exception message. + # + # @api private + # + # @param kwargs [Hash{Symbol => Object}] + # @return [ConvenientService::Exception] + # + # @example Usage. + # module Exceptions + # class Foo < ::ConvenientService::Exception + # def initialize_with_kwargs(**kwargs) + # # message = ... + # initialize(message) + # end + # end + # end + # + # ::ConvenientService.raise Foo.new(foo: :bar, baz: :qux) + # + def new(message = nil, **kwargs) + if message + super(message) + elsif kwargs.any? + allocate.tap { |exception| exception.initialize_with_kwargs(**kwargs) } + else + allocate.tap(&:initialize_without_arguments) + end + end + end + + ## + # @internal + # NOTE: Two exceptions are equal when their classes, messages, and backtraces are equal. + # - https://blog.arkency.com/2015/01/ruby-exceptions-equality + # + # TODO: Compare skipping backtraces? Why? + # + # def ==(other) + # # ... + # end + ## end end