37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
# File 'lib/yarrow/schema.rb', line 37
def self.factory(*slots, **fields, &block)
if slots.empty? && fields.empty?
raise ArgumentError.new("missing attribute definition")
end
slots_spec, fields_spec = if fields.any?
raise ArgumentError.new("cannot use slots when field map is supplied") if slots.any?
[fields.keys, fields]
else
[slots, Hash[slots.map { |s| [s, Type::Any]}]]
end
validator = Validator.new(fields_spec)
struct = Struct.new(*slots_spec, keyword_init: true, &block)
struct.define_method :initialize do |*args, **kwargs|
attr_values = if args.any?
raise ArgumentError.new("cannot mix slots and kwargs") if kwargs.any?
Hash[slots.zip(args)]
else
kwargs
end
validator.check(attr_values)
super(**attr_values)
freeze
end
struct
end
|