-
# frozen_string_literal: true
-
-
1
require "refinements/shared/many"
-
-
1
module Refinements
-
# Provides additional enhancements to the Hash primitive.
-
1
module Hash
-
1
refine ::Hash.singleton_class do
-
5
def infinite = new { |nascence, lacuna| nascence[lacuna] = new(&nascence.default_proc) }
-
-
2
def with_default(value) = new { |nascence, lacuna| nascence[lacuna] = value }
-
end
-
-
1
refine ::Hash do
-
1
import_methods Shared::Many
-
-
14
def compress = compact.delete_if { |_key, value| value.respond_to?(:empty?) && value.empty? }
-
-
1
def compress!
-
19
delete_if { |_key, value| value.respond_to?(:empty?) && value.empty? }
-
4
compact!
-
end
-
-
1
def deep_merge other
-
12
clazz = self.class
-
-
12
merge other do |_key, this_value, other_value|
-
14
then: 6
if this_value.is_a?(clazz) && other_value.is_a?(clazz)
-
6
this_value.deep_merge other_value
-
else: 8
else
-
8
other_value
-
end
-
end
-
end
-
-
1
def deep_merge!(other) = replace(deep_merge(other))
-
-
1
def deep_stringify_keys = recurse(&:stringify_keys)
-
-
1
def deep_stringify_keys! = replace(deep_stringify_keys)
-
-
1
def deep_symbolize_keys = recurse(&:symbolize_keys)
-
-
1
def deep_symbolize_keys! = replace(deep_symbolize_keys)
-
-
1
def diff other
-
5
then: 3
else: 2
return differences_from other if other.is_a?(self.class) && keys.sort! == other.keys.sort!
-
-
7
each.with_object({}) { |(key, value), diff| diff[key] = [value, nil] }
-
end
-
-
1
def fetch_deep(*keys, default: NilClass, &)
-
10
keys.reduce fallback(keys.shift, default, &) do |value, key|
-
13
else: 12
then: 1
unless value.is_a?(::Hash) || (value.is_a?(::Array) && key.is_a?(::Integer))
-
1
fail KeyError, "Unable to find #{key.inspect} in #{value.inspect}."
-
end
-
-
12
then: 11
else: 1
default == NilClass ? value.fetch(key, &) : value.fetch(key, default)
-
end
-
end
-
-
1
def fetch_value(key, *default, &)
-
6
then: 1
else: 1
fetch(key, *default, &) || (yield if block_given?) || default.first
-
end
-
-
1
def flatten_keys prefix: nil, delimiter: "_"
-
28
reduce({}) do |accumulator, (key, value)|
-
38
then: 18
else: 20
flat_key = prefix ? :"#{prefix}#{delimiter}#{key}" : key
-
-
38
else: 14
then: 24
next accumulator.merge flat_key => value unless value.is_a? ::Hash
-
-
28
accumulator.merge(recurse { value.flatten_keys prefix: flat_key, delimiter: })
-
end
-
end
-
-
1
def flatten_keys!(prefix: nil, delimiter: "_") = replace flatten_keys(prefix:, delimiter:)
-
-
1
def recurse &block
-
29
else: 28
then: 1
return self unless block
-
-
28
transform = yield self
-
61
then: 4
else: 29
transform.each { |key, value| transform[key] = value.recurse(&block) if value.is_a? ::Hash }
-
end
-
-
1
def stringify_keys = transform_keys(&:to_s)
-
-
1
def stringify_keys! = transform_keys!(&:to_s)
-
-
1
def symbolize_keys = transform_keys(&:to_sym)
-
-
1
def symbolize_keys! = transform_keys!(&:to_sym)
-
-
1
def transform_value(key, &) = dup.transform_value!(key, &)
-
-
1
def transform_value! key
-
10
then: 6
else: 4
block_given? && key?(key) ? merge!(key => yield(self[key])) : self
-
end
-
-
1
def transform_with(**) = dup.transform_with!(**)
-
-
1
def transform_with!(**operations)
-
14
then: 6
else: 2
operations.each { |key, function| self[key] = function.call self[key] if key? key }
-
6
self
-
end
-
-
1
def use &block
-
3
else: 2
then: 1
return [] unless block
-
-
2
block.parameters
-
4
.map { |(_type, key)| self[key] || self[key.to_s] }
-
2
.then { |values| yield values }
-
end
-
-
1
private
-
-
1
def differences_from other
-
11
result = merge(other.to_h) { |_, one, two| [one, two].uniq }
-
11
result.select { |_, diff| diff.size == 2 }
-
end
-
-
1
def fallback(key, default, &)
-
10
then: 8
else: 2
default == NilClass ? fetch(key, &) : fetch(key, default)
-
end
-
end
-
end
-
end