5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
# File 'lib/archspec/value_object.rb', line 5
def self.define(*members, &block)
klass = Struct.new(*members) do
members.each { |member| undef_method :"#{member}=" }
def initialize(*values, **keywords)
member_names = self.class.members
if keywords.any?
raise ArgumentError, 'expected positional arguments or keyword arguments, not both' unless values.empty?
unknown = keywords.keys - member_names
raise ArgumentError, "unknown keyword: #{unknown.first.inspect}" if unknown.any?
missing = member_names - keywords.keys
raise ArgumentError, "missing keyword: #{missing.first.inspect}" if missing.any?
values = member_names.map { |member| keywords.fetch(member) }
elsif values.length != member_names.length
raise ArgumentError, "wrong number of arguments (given #{values.length}, expected #{member_names.length})"
end
super(*values)
freeze
end
def with(**changes)
unknown = changes.keys - self.class.members
raise ArgumentError, "unknown keyword: #{unknown.first.inspect}" if unknown.any?
self.class.new(**to_h.merge(changes))
end
end
klass.class_eval(&block) if block
klass
end
|