Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ The "Signs And Portents" Update

Added `Cuprum.initializer` to initialize dependencies and error messages. Call `Cuprum.initializer.call` in the entry point or initializers of your application to avoid missing error messages.

### Errors

Errors now support defining messages using `SleepingKingStudios::Tools::Messages` or by defining a `:MESSAGE` constant, including support for named parameters (see `Kernel#format`).

### Results

Added `Result.success` and `Result.failure`, which provide singleton results with respective `:success` and `:failure` statuses.
Expand Down
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ gemspec

gem 'sleeping_king_studios-tasks', '~> 0.4', '>= 0.4.1'

gem 'sleeping_king_studios-tools',
git: 'https://github.com/sleepingkingstudios/sleeping_king_studios-tools'

group :development, :test do
gem 'byebug', '~> 12.0'
gem 'irb', '~> 1.16'
Expand Down
7 changes: 7 additions & 0 deletions config/messages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
cuprum:
errors:
command_not_implemented: 'no implementation defined for %<class_name>s'
invalid_parameters: 'invalid parameters for %<class_name>s - %<failure_messages>s'
multiple_errors: 'the command encountered one or more errors'
operation_not_called: '%<class_name>s was not called and does not have a result'
7 changes: 6 additions & 1 deletion cuprum.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@ Gem::Specification.new do |gem|

gem.required_ruby_version = ['>= 3.1', '< 5']
gem.require_path = 'lib'
gem.files = Dir['lib/**/*.rb', 'LICENSE', '*.md']
gem.files = Dir[
'config/**/*.yml',
'lib/**/*.rb',
'LICENSE',
'*.md'
]

gem.add_runtime_dependency 'sleeping_king_studios-tools', '~> 1.3'
end
2 changes: 1 addition & 1 deletion docs/_constants/cuprum/version/minor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Cuprum::Version::MINOR
parent_path: cuprum/version
slug: minor
short_description: Minor version.
value: '3'
value: '4'
data_path: cuprum/version/minor
metadata:
api: private
Expand Down
2 changes: 1 addition & 1 deletion docs/_constants/cuprum/version/patch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Cuprum::Version::PATCH
parent_path: cuprum/version
slug: patch
short_description: Patch version.
value: '1'
value: '0'
data_path: cuprum/version/patch
metadata:
api: private
Expand Down
2 changes: 1 addition & 1 deletion docs/_constants/cuprum/version/prerelease.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Cuprum::Version::PRERELEASE
parent_path: cuprum/version
slug: prerelease
short_description: Prerelease version.
value: nil
value: ":alpha"
data_path: cuprum/version/prerelease
metadata:
api: private
Expand Down
12 changes: 12 additions & 0 deletions docs/_methods/cuprum/c-gem-path.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
name: Cuprum.gem_path
parent_path: cuprum
signature: gem_path
slug: gem-path
constructor: false
data_path: cuprum/c-gem-path
returns:
- description: the absolute path to the gem directory.
type:
- name: String
version: "*"
4 changes: 4 additions & 0 deletions docs/_modules/cuprum.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ class_attributes:
slug: initializer
inherited: false
class_methods:
- name: gem_path
path: cuprum/c-gem-path
slug: gem-path
inherited: false
- name: version
path: cuprum/c-version
slug: version
Expand Down
16 changes: 16 additions & 0 deletions lib/cuprum.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ module Cuprum
autoload :CommandFactory, 'cuprum/command_factory'
autoload :Currying, 'cuprum/currying'
autoload :Error, 'cuprum/error'
autoload :Errors, 'cuprum/errors'
autoload :ExceptionHandling, 'cuprum/exception_handling'
autoload :MapCommand, 'cuprum/map_command'
autoload :Matcher, 'cuprum/matcher'
Expand All @@ -20,13 +21,28 @@ module Cuprum

@initializer = SleepingKingStudios::Tools::Toolbox::Initializer.new do
SleepingKingStudios::Tools.initializer.call

SleepingKingStudios::Tools::Messages::Registry
.global
.register(
file: File.join(Cuprum.gem_path, 'config', 'messages.yml'),
scope: 'cuprum.errors'
)
end

class << self
# @return [SleepingKingStudios::Tools::Toolbox::Initializer] the initializer
# for the module.
attr_reader :initializer

# @return [String] the absolute path to the gem directory.
def gem_path
sep = File::SEPARATOR
pattern = /#{sep}lib#{sep}?\z/

__dir__.sub(pattern, '')
end

# @return [String] the current version of the gem.
def version
VERSION
Expand Down
24 changes: 22 additions & 2 deletions lib/cuprum/error.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ class Error
# @param properties [Hash] Additional properties used to compare errors.
# @param type [String] Short string used to identify the type of error.
def initialize(message: nil, type: nil, **properties)
@message = message
@type = type || self.class::TYPE
@type = type || self.class::TYPE
@message = message || default_message_for(**properties)
@comparable_properties = properties.merge(message:, type:)
end

Expand Down Expand Up @@ -109,5 +109,25 @@ def as_json
def as_json_data
{}
end

def default_message_for(**parameters)
if type && !(type.respond_to?(:empty?) && type.empty?)
message = tools.messages.message(type, default: nil, parameters:)

return message if message
end

format_default_message(parameters)
end

def format_default_message(parameters)
return unless self.class.const_defined?(:MESSAGE)

format(self.class::MESSAGE, parameters)
rescue KeyError => exception
"Message missing parameters: #{type} #{exception.message}"
end

def tools = SleepingKingStudios::Tools::Toolbelt.instance
end
end
6 changes: 1 addition & 5 deletions lib/cuprum/errors/command_not_implemented.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ class CommandNotImplemented < Cuprum::Error
COMPARABLE_PROPERTIES = %i[command].freeze
private_constant :COMPARABLE_PROPERTIES

MESSAGE_FORMAT = 'no implementation defined for %s'
private_constant :MESSAGE_FORMAT

# Short string used to identify the type of error.
TYPE = 'cuprum.errors.command_not_implemented'

Expand All @@ -20,9 +17,8 @@ def initialize(command:)
@command = command

class_name = command&.class&.name || 'command'
message = MESSAGE_FORMAT % class_name

super(command:, message:)
super(class_name:, command:)
end

# @return [Cuprum::Command] The command called without a definition.
Expand Down
13 changes: 6 additions & 7 deletions lib/cuprum/errors/invalid_parameters.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,16 @@ class InvalidParameters < Cuprum::Error
# @param command_class [Class] the class of the failed command.
# @param failures [Array<String>] the messages for the failed validations.
def initialize(command_class:, failures:)
@command_class = command_class
@failures = failures
@command_class = command_class
@failures = failures
class_name = command_class.name
failure_messages = failures.join(', ')

super(
class_name:,
command_class:,
failures:,
message: generate_message
failure_messages:
)
end

Expand All @@ -36,9 +39,5 @@ def as_json_data
'failures' => failures.map(&:to_s)
}
end

def generate_message
"invalid parameters for #{command_class.name} - #{failures.join(', ')}"
end
end
end
9 changes: 1 addition & 8 deletions lib/cuprum/errors/multiple_errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@ class MultipleErrors < Cuprum::Error
def initialize(errors:, message: nil)
@errors = errors

super(
errors:,
message: message || default_message
)
super
end

# @return [Array<Cuprum::Error>] the wrapped errors.
Expand All @@ -31,9 +28,5 @@ def as_json_data
'errors' => errors.map { |error| error&.as_json }
}
end

def default_message
'the command encountered one or more errors'
end
end
end
7 changes: 1 addition & 6 deletions lib/cuprum/errors/operation_not_called.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,15 @@
module Cuprum::Errors
# Error returned when trying to access the result of an uncalled Operation.
class OperationNotCalled < Cuprum::Error
MESSAGE_FORMAT = '%s was not called and does not have a result'
private_constant :MESSAGE_FORMAT

# Short string used to identify the type of error.
TYPE = 'cuprum.errors.operation_not_called'

# @param operation [Cuprum::Operation] The uncalled operation.
def initialize(operation:)
@operation = operation

class_name = operation&.class&.name || 'operation'
message = MESSAGE_FORMAT % class_name

super(message:, operation:)
super(class_name:, message:, operation:)
end

# @return [Cuprum::Operation] The uncalled operation.
Expand Down
6 changes: 3 additions & 3 deletions lib/cuprum/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ module Version
# Major version.
MAJOR = 1
# Minor version.
MINOR = 3
MINOR = 4
# Patch version.
PATCH = 1
PATCH = 0
# Prerelease version.
PRERELEASE = nil
PRERELEASE = :alpha
# Build metadata.
BUILD = nil

Expand Down
Loading