Class: Plumb::HashClass
Constant Summary
collapse
- NOT_A_HASH =
{ _: 'must be a Hash' }.freeze
Instance Attribute Summary collapse
Instance Method Summary
collapse
Methods included from Composable
#>>, #as_node, #build, #check, #children, #defer, #generate, included, #invalid, #invoke, #match, #metadata, #not, #pipeline, #policy, #static, #to_json_schema, #to_s, #transform, #value, wrap, #|
Methods included from Callable
#parse, #resolve
Constructor Details
#initialize(schema: BLANK_HASH, inclusive: false) ⇒ HashClass
Returns a new instance of HashClass.
17
18
19
20
21
|
# File 'lib/plumb/hash_class.rb', line 17
def initialize(schema: BLANK_HASH, inclusive: false)
@_schema = wrap_keys_and_values(schema)
@inclusive = inclusive
freeze
end
|
Instance Attribute Details
#_schema ⇒ Object
Returns the value of attribute _schema.
15
16
17
|
# File 'lib/plumb/hash_class.rb', line 15
def _schema
@_schema
end
|
Instance Method Details
#&(other) ⇒ Object
59
60
61
62
63
64
65
66
67
68
|
# File 'lib/plumb/hash_class.rb', line 59
def &(other)
raise ArgumentError, "expected a HashClass, got #{other.class}" unless other.is_a?(HashClass)
intersected_keys = other._schema.keys & _schema.keys
intersected = intersected_keys.each.with_object({}) do |k, memo|
memo[k] = other.at_key(k)
end
self.class.new(schema: intersected, inclusive: @inclusive)
end
|
#+(other) ⇒ Object
Hash#merge keeps the left-side key in the new hash if they match via #hash and #eql? we need to keep the right-side key, because even if the key name is the same, it’s optional flag might have changed
48
49
50
51
52
53
54
55
56
57
|
# File 'lib/plumb/hash_class.rb', line 48
def +(other)
other_schema = case other
when HashClass then other._schema
when ::Hash then other
else
raise ArgumentError, "expected a HashClass or Hash, got #{other.class}"
end
self.class.new(schema: merge_rightmost_keys(_schema, other_schema), inclusive: @inclusive)
end
|
#==(other) ⇒ Object
131
132
133
|
# File 'lib/plumb/hash_class.rb', line 131
def ==(other)
other.is_a?(self.class) && other._schema == _schema
end
|
#at_key(a_key) ⇒ Object
78
79
80
|
# File 'lib/plumb/hash_class.rb', line 78
def at_key(a_key)
_schema[Key.wrap(a_key)]
end
|
#call(result) ⇒ Object
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
# File 'lib/plumb/hash_class.rb', line 106
def call(result)
return result.invalid(errors: NOT_A_HASH) unless result.value.is_a?(::Hash)
return result unless _schema.any?
input = result.value
errors = {}
field_result = result.dup
initial = {}
initial = initial.merge(input) if @inclusive
output = _schema.each.with_object(initial) do |(key, field), ret|
key_s = key.to_sym
if input.key?(key_s)
r = field.call(field_result.reset(input[key_s]))
errors[key_s] = r.errors unless r.valid?
ret[key_s] = r.value
elsif !key.optional?
r = field.call(BLANK_RESULT)
errors[key_s] = r.errors unless r.valid?
ret[key_s] = r.value unless r.value == Undefined
end
end
errors.any? ? result.invalid(output, errors:) : result.valid(output)
end
|
#filtered ⇒ Object
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
# File 'lib/plumb/hash_class.rb', line 84
def filtered
op = lambda do |result|
return result.invalid(errors: 'must be a Hash') unless result.value.is_a?(::Hash)
return result unless _schema.any?
input = result.value
field_result = BLANK_RESULT.dup
output = _schema.each.with_object({}) do |(key, field), ret|
key_s = key.to_sym
if input.key?(key_s)
r = field.call(field_result.reset(input[key_s]))
ret[key_s] = r.value if r.valid?
elsif !key.optional?
r = field.call(BLANK_RESULT)
ret[key_s] = r.value if r.valid?
end
end
result.valid(output)
end
Step.new(op, [_inspect, 'filtered'].join('.'))
end
|
#inclusive ⇒ Object
74
75
76
|
# File 'lib/plumb/hash_class.rb', line 74
def inclusive
self.class.new(schema: _schema, inclusive: true)
end
|
#schema(*args) ⇒ Object
Also known as:
[]
31
32
33
34
35
36
37
38
39
40
|
# File 'lib/plumb/hash_class.rb', line 31
def schema(*args)
case args
in [::Hash => hash]
self.class.new(schema: _schema.merge(wrap_keys_and_values(hash)), inclusive: @inclusive)
in [key_type, value_type]
HashMap.new(Composable.wrap(key_type), Composable.wrap(value_type))
else
raise ::ArgumentError, "unexpected value to Types::Hash#schema #{args.inspect}"
end
end
|
#tagged_by(key, *types) ⇒ Object
70
71
72
|
# File 'lib/plumb/hash_class.rb', line 70
def tagged_by(key, *types)
TaggedHash.new(self, key, types)
end
|
#to_h ⇒ Object
82
|
# File 'lib/plumb/hash_class.rb', line 82
def to_h = _schema
|