Module: LazyGraph::HashUtils

Defined in:
lib/lazy_graph/hash_utils.rb

Class Method Summary collapse

Class Method Details

.deep_dup(obj, symbolize: false, signature: nil) ⇒ Object

Deeply duplicates a nested hash or array, preserving object identity. Optionally symbolizes keys on the way, and/or generates a signature.



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/lazy_graph/hash_utils.rb', line 9

def deep_dup(obj, symbolize: false, signature: nil)
  case obj
  when Hash
    obj.each_with_object(symbolize ? {}.compare_by_identity : {}) do |(key, value), result|
      key = \
        if !symbolize || key.is_a?(Symbol)
          key
        else
          key.is_a?(String) ? key.to_sym : key.to_s.to_sym
        end

      signature[0] ^= key.object_id if signature
      result[key] = deep_dup(value, symbolize: symbolize, signature: signature)
    end
  when Array
    obj.map { |value| deep_dup(value, symbolize: symbolize, signature: signature) }
  when String, Numeric, TrueClass, FalseClass, NilClass
    signature[0] ^= obj.hash if signature
    obj
  else
    obj
  end
end

.deep_merge(hash, other_hash, path = '') ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/lazy_graph/hash_utils.rb', line 33

def deep_merge(hash, other_hash, path = '')
  hash.merge(other_hash.transform_keys(&:to_sym)) do |key, this_val, other_val|
    current_path = path.empty? ? key.to_s : "#{path}.#{key}"

    if this_val.is_a?(Hash) && other_val.is_a?(Hash) && other_val != this_val
      deep_merge(this_val, other_val, current_path)
    elsif this_val.is_a?(Array) && other_val.is_a?(Array) && other_val != this_val
      (this_val | other_val)
    else
      if this_val != other_val && !(this_val.is_a?(Proc) && other_val.is_a?(Proc))
        LazyGraph.logger.warn("Conflicting values at #{current_path}: #{this_val.inspect} != #{other_val.inspect}")
      end
      other_val
    end
  end
end

.strip_invalid(obj, parent_list = {}.compare_by_identity) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/lazy_graph/hash_utils.rb', line 50

def strip_invalid(obj, parent_list = {}.compare_by_identity)
  return { '^ref': :circular } if (circular_dependency = parent_list[obj])

  parent_list[obj] = true
  case obj
  when Hash
    obj.each_with_object({}) do |(key, value), obj|
      next if value.is_a?(MissingValue)

      obj[key] = strip_invalid(value, parent_list)
    end
  when Struct
    obj.members.each_with_object({}) do |key, res|
      next if obj[key].is_a?(MissingValue)
      next if obj.invisible.include?(key)

      res[key] = strip_invalid(obj[key], parent_list)
    end
  when Array
    obj.map { |value| strip_invalid(value, parent_list) }
  when MissingValue
    nil
  else
    obj
  end
ensure
  parent_list.delete(obj) unless circular_dependency
end