Class: Deterministic::InstanceBuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/deterministic/protocol.rb

Instance Method Summary collapse

Constructor Details

#initialize(protocol, type, block) ⇒ InstanceBuilder

Returns a new instance of InstanceBuilder.



43
44
45
46
# File 'lib/deterministic/protocol.rb', line 43

def initialize(protocol, type, block)
  @protocol, @type, @block = protocol, type, block
  @instance = Class.new(@protocol::Protocol)
end

Instance Method Details

#buildObject

Raises:

  • (NotImplementedError)


48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# 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