# frozen_string_literal: true require 'luna_park/errors/business' require 'luna_park/errors/system' module LunaPark module Extensions ## # This is syntax sugar for define exception class # in UseCase layer # # @example without sugar # class Service # class UserNotExists < LunaPark::Errors::Business # message 'Sorry but user does not exists' # end # # def call # raise UserNotExists if something_wrong # end # end # # @example with sugar # class Service # include LunaPark::Extensions::HasErrors # error :user_not_exists, 'Sorry but user does not exists' # # def call # error :user_not_exists if something_wrong # end # end module HasErrors def self.included(base) base.extend ClassMethods base.include InstanceMethods end module InstanceMethods ## # Raise error defined in class # # @example # class Service # include LunaPark::Extensions::HasErrors # # class CustomError < LunaPark::Errors::Business; end # end # # Service.new.error :custom_error # => raise CustomError # # @param title [Symbol|String] - Title of error # @param msg [String] - Message of error # @param **attrs - See @LunaPark::Errors::Base#new def error(title, msg = nil, **attrs) class_name = self.class.error_class_name(title) raise self.class.const_get(class_name).new msg, **attrs end end module ClassMethods ## # Define business error # # @example # class Service # include LunaPark::Extensions::HasErrors # # business_error :logic_error, { (1 + 1).to_s } # end # # logic_error = Service::LogicError.new # logic_error.is_a? LunaPark::Errors::Business # => true # logic_error.message # => '2' def business_error(title, txt = nil, i18n_key: nil, notify: nil, &default_message_block) error_class = Class.new(Errors::Business) error_class.message(txt, i18n_key: i18n_key, &default_message_block) error_class.notify(notify) const_set(error_class_name(title), error_class) end ## # Alias for business error alias error business_error ## # Define business error # # @example # class Service # include LunaPark::Extensions::HasErrors # # system_error :tech_error, 'Custom message' # end # # tech_error = Service::TechError.new # tech_error.is_a? LunaPark::Errors::System # => true # tech_error.message # => 'Custom message' def system_error(title, txt = nil, i18n_key: nil, notify: nil, &default_message_block) error_class = Class.new(Errors::System) error_class.message(txt, i18n_key: i18n_key, &default_message_block) error_class.notify(notify) const_set(error_class_name(title), error_class) end ## # Get error class name # # @example when title is string # error_class_name('CamelCase') # => 'CamelCase' # # @example when title is symbol # error_class_name(:snake_case) # => 'SnakeCase' # # @param [String|Symbol] title - short alias for error def error_class_name(title) case title when String then title when Symbol then title.to_s.split('_').collect!(&:capitalize).join else raise ArgumentError, "Unknown type `#{title}` for error title" end end end end end end