lib/atacama/contract.rb in atacama-0.1.3 vs lib/atacama/contract.rb in atacama-0.1.4
- old
+ new
@@ -7,10 +7,27 @@
module Atacama
# The type namespace to interact with DRY::Types
module Types
include Dry::Types.module
Boolean = Types::True | Types::False
+
+ def self.Option(**map)
+ Instance(Values::Option).constructor do |options|
+ map.each do |key, type|
+ type[options.value[key]]
+ end
+
+ options
+ end
+ end
+
+ def self.Return(type)
+ Instance(Values::Return).constructor do |options|
+ type[options.value]
+ options
+ end
+ end
end
# This class enables a DSL for creating a contract for the initializer
class Contract
RESERVED_KEYS = %i[call initialize context].freeze
@@ -24,33 +41,48 @@
def injected=(hash)
@injected = Types::Strict::Hash[hash]
end
def injected
- @injected || {}
+ # Silences the VM warning about accessing uninitalized ivar
+ defined?(@injected) ? @injected : {}
end
def options
@options ||= {}
end
+ def returns(type)
+ @returns = type
+ end
+
+ def return_type
+ defined?(@returns) && @returns
+ end
+
+ def validate_return(value)
+ return_type && return_type[value]
+ end
+
# Define an initializer value.
# @param [Symbol] name of the argument
def option(name, **kwargs)
options[NameInterface[name]] = Parameter.new(name: name, **kwargs)
define_method(name) { @context[name] }
define_method("#{name}?") { !!@context[name] }
end
def call(context = {})
- new(context: context).call
+ new(context: context).call.tap do |result|
+ validate_return(result)
+ end
end
def inject(injected)
- Class.new(self) do
- self.injected = injected
+ clone.tap do |clone|
+ clone.injected = injected
end
end
end
attr_reader :context
@@ -61,9 +93,19 @@
@context = Context.new(self.class.injected).tap do |ctx|
ctx.merge!(context.is_a?(Context) ? context.to_h : context)
end
Validator.call(options: self.class.options, context: @context)
+ end
+
+ # Pretty pretty printing.
+ def inspect
+ "#<#{self.class}:0x%x %s>" % [
+ object_id,
+ self.class.options.keys.map do |option|
+ "#{option}: #{context.send(option).inspect}"
+ end.join(' ')
+ ]
end
def call
self
end