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