Class: Hash

Inherits:
Object
  • Object
show all
Includes:
IS::Deep
Defined in:
lib/is-deep.rb

Instance Method Summary collapse

Methods included from IS::Deep

#deep_merge

Instance Method Details

#can_merge?(other) ⇒ Boolean

Checks if other can be merged with this hash.

Parameters:

  • other (Object)

    Object to check

Returns:

  • (Boolean)

    True if other is hash-like



92
93
94
# File 'lib/is-deep.rb', line 92

def can_merge?(other)
  other.is_a?(Hash) || other.respond_to?(:to_hash)
end

#deep_dupHash

Creates deep copy of hash with all nested structures.

Handles circular references correctly. Preserves default values and default_proc if present.

Examples:

h = { a: { b: 1 } }
copy = h.deep_dup
copy[:a][:b] = 2
h[:a][:b] # => 1 (unchanged)

Returns:

  • (Hash)

    Deep copy of self



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/is-deep.rb', line 20

def deep_dup
  visited_wrap do |visited|
    self_id = self.object_id
    return visited[self_id] if visited.has_key?(self_id)
    result = {}
    visited[self_id] = result
    if self.default_proc != nil
      result.default_proc = self.default_proc
    elsif self.default != nil
      result.default = self.default
    end
    self.each do |key, value|
      id = value.object_id
      result[key] = if visited.has_key?(id)
        visited[id]
      elsif value.respond_to?(:deep_dup)
        visited[id] = value.deep_dup
      elsif value.respond_to?(:dup)
        visited[id] = value.dup
      else
        visited[id] = value
      end
    end
    result
  end
end

#deep_merge!(other, array_strategy: nil) ⇒ self

Deep merges other hash into self, modifying receiver.

Recursively merges nested hashes. For conflicting values where old value responds to #can_merge? and returns true, attempts recursive merge. Otherwise replaces with new value.

Examples:

h = { a: { b: 1 } }
h.deep_merge!({ a: { c: 2 } })
h # => { a: { b: 1, c: 2 } }

Parameters:

  • other (Hash, #to_hash)

    Hash or hash-like object to merge

  • array_strategy (#call, nil) (defaults to: nil)

    Override array merge strategy

Returns:

  • (self)

    Modified receiver



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/is-deep.rb', line 60

def deep_merge! other, array_strategy: nil
  visited_wrap do |visited|
    id = self.object_id
    return self if visited.has_key?(id)
    visited[id] = self
    source = if other.is_a?(Hash)
      other
    elsif other.respond_to?(:to_hash)
      other.to_hash
    else
      raise ArgumentError, "Unsupported type of source: (#{ other.class })", caller_locations
    end
    source.each do |key, value|
      if self.has_key?(key)
        old = self[key]
        if old.respond_to?(:can_merge?) && old.can_merge?(value)
          old.deep_merge! value, array_strategy: array_strategy
        else
          self[key] = value
        end
      else
        self[key] = value
      end
    end
    self
  end
end