Class: Hash

Inherits:
Object
  • Object
show all
Includes:
HashMiner
Defined in:
lib/hash_miner/hash.rb

Overview

Adds additional methods to the Hash class

Constant Summary

Constants included from HashMiner

HashMiner::LOG, HashMiner::VERSION

Instance Method Summary collapse

Instance Method Details

#deep_compactHash

Removed nil/empty from Hash

Returns:

  • (Hash)

    with no nil/empty values



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/hash_miner/hash.rb', line 66

def deep_compact
  if is_a?(Hash)
    to_h do |k, v|
      case v
      when Hash
        [k, v.deep_compact]
      when Array
        [k, v.map do |i|
          i.is_a?(Hash) ? i.deep_compact : i
        end]
      else
        [k, v]
      end
    end.delete_if { |_, v| v.nil? || (v.respond_to?(:empty?) && v.empty?) }
  else
    self
  end
end

#deep_contains?(key:, hash: self) ⇒ Boolean

Checks if the key exists within a Hash

Parameters:

  • key (String, Symbol)

    the key you want to check

  • hash (Hash) (defaults to: self)

    the hash obj - used for recursive calling

Returns:

  • (Boolean)

    whether the key was found



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/hash_miner/hash.rb', line 13

def deep_contains?(key:, hash: self)
  return false unless hash.is_a? Hash
  return true if hash.include? key

  hash.filter_map do |_k, v|
    case v
    when Hash
      [v.deep_contains?(key: key)]
    when Array
      [v.map { |i| deep_contains?(key: key, hash: i) }]
    else
      false
    end
  end.flatten.include? true
end

#deep_count(key:, hash: self) ⇒ Integer

Count the number of occurrences a key has in a Hash

Parameters:

  • key (String, Symbol)
  • hash (Hash) (defaults to: self)

Returns:

  • (Integer)

    the number of occurrences for a given key



35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/hash_miner/hash.rb', line 35

def deep_count(key:, hash: self)
  found = 0
  return found unless hash.is_a? Hash
  return found unless hash.deep_contains?(key: key)

  hash.each do |k, v|
    found += 1 if k.eql? key
    found += deep_count(hash: v, key: key) if v.is_a?(Hash)
    v.each { |i| found += deep_count(hash: i, key: key) } if v.is_a?(Array)
  end

  found
end

#deep_find(key:, hash: self, parent: nil) ⇒ Array

Finds the value for a given key

Parameters:

  • key (String, Symbol)
  • hash (Hash) (defaults to: self)
  • parent (String, Symbol, Array) (defaults to: nil)

Returns:

  • (Array)

    with all values that match the key



56
57
58
59
60
61
# File 'lib/hash_miner/hash.rb', line 56

def deep_find(key:, hash: self, parent: nil)
  return nil unless hash.is_a? Hash
  return nil unless hash.deep_contains?(key: key)

  parent ? deep_find_parent_logic(hash: self, key: key, parent: parent) : deep_find_logic(hash: self, key: key)
end

#deep_remove(key:, error_on_uniqueness: true, parent: nil) ⇒ Hash

Removes specified key from nested hash.

Parameters:

  • key (String)

    the key to remove.

  • error_on_uniqueness (Boolean) (defaults to: true)

    error if key not unique

  • parent (String, Symbol, Array) (defaults to: nil)

    the parent key for the key you want to update

Returns:

  • (Hash)

    the object with specified key removed.



128
129
130
131
132
133
134
135
136
# File 'lib/hash_miner/hash.rb', line 128

def deep_remove(key:, error_on_uniqueness: true, parent: nil)
  return self unless is_a? Hash

  if error_on_uniqueness && (deep_count(key: key) > 1)
    raise KeyNotUniqueError, "Key: '#{key}' not unique | Pass 'error_on_uniqueness: false' if you do not care"
  end

  parent ? deep_remove_logic_parent(hash: self, key: key, parent: parent) : deep_remove_logic(hash: self, key: key)
end

#deep_update(key:, value:, error_on_missing: true, error_on_uniqueness: true, parent: nil) ⇒ Hash

Updates specified key in nested hash.

Parameters:

  • key (String, Symbol)

    the key to update

  • value (String)

    the value to be set

  • error_on_missing (Boolean) (defaults to: true)

    error if key missing

  • error_on_uniqueness (Boolean) (defaults to: true)

    error if key not unique

  • parent (String, Symbol, Array) (defaults to: nil)

    the parent key for the key you want to update

Returns:

  • (Hash)

    the object with specified key updated.



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/hash_miner/hash.rb', line 94

def deep_update(key:, value:, error_on_missing: true, error_on_uniqueness: true, parent: nil)
  return self unless is_a? Hash

  if error_on_uniqueness && (deep_count(key: key) > 1)
    raise KeyNotUniqueError, "Key: '#{key}' not unique | Pass 'error_on_uniqueness: false' if you do not care"
  end

  unless deep_contains?(key: key)
    if error_on_missing
      raise KeyNotFoundError,
            "Key: '#{key}' not found in hash | Pass 'error_on_missing: false' if you do not care"
    end

    LOG.warn('Key not found in hash, adding to the top level')

    hash = dup
    hash[key] = value
    return hash
  end

  if parent
    deep_update_parent_flow(hash: self, key: key, value: value, parent: parent)
  else
    deep_update_logic(hash: self, key: key, value: value)
  end
end