class Deterministic::InstanceBuilder
Public Class Methods
new(protocol, type, block)
click to toggle source
# File lib/deterministic/protocol.rb, line 43 def initialize(protocol, type, block) @protocol, @type, @block = protocol, type, block @instance = Class.new(@protocol::Protocol) end
Public Instance Methods
build()
click to toggle source
# File lib/deterministic/protocol.rb, line 48 def build @instance.class_exec(&@block) protocol = @protocol::Protocol methods = protocol.methods(false) inst_type = @type @instance.instance_exec { methods.each { |name| if method_defined?(name) meth = instance_method(name) signature = protocol.send(name) params = signature.params expect_type = inst_type[signature.return_type] define_method(name) { |*args| args.each_with_index { |arg, i| name = params.keys[i] arg_type = params.fetch(name) expect_arg_type = inst_type.fetch(arg_type) raise TypeError, "Expected arg #{name} to be a #{expect_arg_type}, got #<#{arg.class}: #{arg.inspect}>" unless arg.is_a? expect_arg_type } result = meth.bind(self).call(*args) raise TypeError, "Expected #{name}(#{args.join(', ')}) to return a #{expect_type}, got #<#{result.class}: #{result.inspect}>" unless result.is_a? expect_type result } end } } missing = methods.detect { |m| !@instance.instance_methods(false).include?(m) } raise NotImplementedError, "`#{missing}` has no default implementation for #{@protocol} #{@type.to_s}" unless missing.nil? @instance end