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, #where, #with, 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
137
138
139
|
# File 'lib/plumb/hash_class.rb', line 137
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
130
131
132
133
134
135
|
# 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 = nil output = @inclusive ? input.dup : {}
field_result = Result.valid(nil)
_schema.each do |key, field|
key_s = key.to_key
if input.key?(key_s)
r = field.call(field_result.reset(input[key_s]))
output[key_s] = r.value
unless r.valid?
errors ||= {}
errors[key_s] = r.errors
end
elsif !key.optional?
r = field.call(BLANK_RESULT)
output[key_s] = r.value unless r.value == Undefined
unless r.valid?
errors ||= {}
errors[key_s] = r.errors
end
end
end
errors ? 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
|