Class: Hash

Inherits:
Object show all
Defined in:
lib/chozo/core_ext/hash/keys.rb,
lib/chozo/core_ext/hash/dotted_paths.rb

Overview

Direct Known Subclasses

Hashie::Hash

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.from_dotted_path(dotpath, seed = nil, target = self.new) ⇒ Hash

Create a new Hash containing other nested Hashes from a string containing a dotted path. A Hash will be created and assigned to a key of another Hash for each entry in the dotted path.

If a value is provided for the optional seed argument then the value of the deepest nested key will be set to the given value. If no value is provided the value of the key will be nil.

Examples:

creating a nested hash from a dotted path


Hash.from_dotted_path("deep.nested.hash") =>
{
  "deep" => {
    "nested" => {
      "hash" => nil
    }
  }
}

specifying a seed value


Hash.from_dotted_path("deep.nested.hash", :seed_value) =>
{
  "deep" => {
    "nested" => {
      "hash" => :seed_value
    }
  }
}

Parameters:

  • dotpath (String, Symbol, Array)
  • seed (Object) (defaults to: nil)

    (nil)

  • target (Hash) (defaults to: self.new)

    (self.new)

Returns:



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/chozo/core_ext/hash/dotted_paths.rb', line 39

def from_dotted_path(dotpath, seed = nil, target = self.new)
  case dotpath
  when String, Symbol
    from_dotted_path(dotpath.to_s.split("."), seed)
  when Array
    if dotpath.empty?
      return target
    end

    key = dotpath.pop

    if target.empty?
      target[key] = seed
      from_dotted_path(dotpath, seed, target)
    else
      new_target = self.new
      new_target[key] = target
      from_dotted_path(dotpath, seed, new_target)
    end
  end
end

Instance Method Details

#assert_valid_keys(*valid_keys) ⇒ Object

Validate all keys in a hash match *valid_keys, raising ArgumentError on a mismatch. Note that keys are NOT treated indifferently, meaning if you use strings for keys but assert symbols as keys, this will fail.

{ name: 'Rob', years: '28' }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key: years"
{ name: 'Rob', age: '28' }.assert_valid_keys('name', 'age') # => raises "ArgumentError: Unknown key: name"
{ name: 'Rob', age: '28' }.assert_valid_keys(:name, :age)   # => passes, raises nothing


70
71
72
73
74
75
# File 'lib/chozo/core_ext/hash/keys.rb', line 70

def assert_valid_keys(*valid_keys)
  valid_keys.flatten!
  each_key do |k|
    raise ArgumentError.new("Unknown key: #{k}") unless valid_keys.include?(k)
  end
end

#deep_stringify_keysObject

Return a new hash with all keys converted to strings. This includes the keys from the root hash and from all nested hashes.

hash = { person: { name: 'Rob', age: '28' } }

hash.deep_stringify_keys
# => { "person" => { "name" => "Rob", "age" => "28" } }


112
113
114
# File 'lib/chozo/core_ext/hash/keys.rb', line 112

def deep_stringify_keys
  deep_transform_keys{ |key| key.to_s }
end

#deep_stringify_keys!Object

Destructively convert all keys to strings. This includes the keys from the root hash and from all nested hashes.



119
120
121
# File 'lib/chozo/core_ext/hash/keys.rb', line 119

def deep_stringify_keys!
  deep_transform_keys!{ |key| key.to_s }
end

#deep_symbolize_keysObject

Return a new hash with all keys converted to symbols, as long as they respond to to_sym. This includes the keys from the root hash and from all nested hashes.

hash = { 'person' => { 'name' => 'Rob', 'age' => '28' } }

hash.deep_symbolize_keys
# => { person: { name: "Rob", age: "28" } }


131
132
133
# File 'lib/chozo/core_ext/hash/keys.rb', line 131

def deep_symbolize_keys
  deep_transform_keys{ |key| key.to_sym rescue key }
end

#deep_symbolize_keys!Object

Destructively convert all keys to symbols, as long as they respond to to_sym. This includes the keys from the root hash and from all nested hashes.



138
139
140
# File 'lib/chozo/core_ext/hash/keys.rb', line 138

def deep_symbolize_keys!
  deep_transform_keys!{ |key| key.to_sym rescue key }
end

#deep_transform_keys(&block) ⇒ Object

Return a new hash with all keys converted by the block operation. This includes the keys from the root hash and from all nested hashes.

hash = { person: { name: 'Rob', age: '28' } }

hash.deep_transform_keys{ |key| key.to_s.upcase }
# => { "PERSON" => { "NAME" => "Rob", "AGE" => "28" } }


85
86
87
88
89
90
91
# File 'lib/chozo/core_ext/hash/keys.rb', line 85

def deep_transform_keys(&block)
  result = {}
  each do |key, value|
    result[yield(key)] = value.is_a?(Hash) ? value.deep_transform_keys(&block) : value
  end
  result
end

#deep_transform_keys!(&block) ⇒ Object

Destructively convert all keys by using the block operation. This includes the keys from the root hash and from all nested hashes.



96
97
98
99
100
101
102
# File 'lib/chozo/core_ext/hash/keys.rb', line 96

def deep_transform_keys!(&block)
  keys.each do |key|
    value = delete(key)
    self[yield(key)] = value.is_a?(Hash) ? value.deep_transform_keys!(&block) : value
  end
  self
end

#dig(path) ⇒ Object?

Return the value of the nested hash key from the given dotted path

Examples:


nested_hash = {
  "deep" => {
    "nested" => {
      "hash" => :seed_value
    }
  }
}

nested_hash.dig('deep.nested.hash') => :seed_value

Parameters:

  • path (String)

Returns:



79
80
81
82
83
84
85
86
87
88
89
# File 'lib/chozo/core_ext/hash/dotted_paths.rb', line 79

def dig(path)
  return nil unless path.present?

  parts = path.split('.', 2)
  match = self[parts[0].to_s].nil? ? self[parts[0].to_sym] : self[parts[0].to_s]
  if !parts[1] or match.nil?
    match
  else
    match.dig(parts[1])
  end
end

#dotted_paths(source = self, acc = Array.new, namespace = Array.new) ⇒ Array<String>

Returns an array of dotted paths from the keys, values of this Hash. Values which are nested Hashes will also recurred into and their paths will be added properly.

Parameters:

  • source (Hash) (defaults to: self)
  • acc (Array) (defaults to: Array.new)
  • namespace (Array) (defaults to: Array.new)

Returns:

  • (Array<String>)


99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/chozo/core_ext/hash/dotted_paths.rb', line 99

def dotted_paths(source = self, acc = Array.new, namespace = Array.new)
  if source.is_a?(Hash) && !source.empty?
    source.each do |key, value|
      branch = namespace.dup
      branch << key
      dotted_paths(value, acc, branch)
    end
  else
    acc << namespace.join('.')
  end

  acc
end

#stringify_keysObject

Return a new hash with all keys converted to strings.

hash = { name: 'Rob', age: '28' }

hash.stringify_keys
#=> { "name" => "Rob", "age" => "28" }


34
35
36
# File 'lib/chozo/core_ext/hash/keys.rb', line 34

def stringify_keys
  transform_keys{ |key| key.to_s }
end

#stringify_keys!Object

Destructively convert all keys to strings. Same as stringify_keys, but modifies self.



40
41
42
# File 'lib/chozo/core_ext/hash/keys.rb', line 40

def stringify_keys!
  transform_keys!{ |key| key.to_s }
end

#symbolize_keysObject Also known as: to_options

Return a new hash with all keys converted to symbols, as long as they respond to to_sym.

hash = { 'name' => 'Rob', 'age' => '28' }

hash.symbolize_keys
#=> { name: "Rob", age: "28" }


51
52
53
# File 'lib/chozo/core_ext/hash/keys.rb', line 51

def symbolize_keys
  transform_keys{ |key| key.to_sym rescue key }
end

#symbolize_keys!Object Also known as: to_options!

Destructively convert all keys to symbols, as long as they respond to to_sym. Same as symbolize_keys, but modifies self.



58
59
60
# File 'lib/chozo/core_ext/hash/keys.rb', line 58

def symbolize_keys!
  transform_keys!{ |key| key.to_sym rescue key }
end

#transform_keysObject

Return a new hash with all keys converted using the block operation.

hash = { name: 'Rob', age: '28' }

hash.transform_keys{ |key| key.to_s.upcase }
# => { "NAME" => "Rob", "AGE" => "28" }


11
12
13
14
15
16
17
# File 'lib/chozo/core_ext/hash/keys.rb', line 11

def transform_keys
  result = {}
  each_key do |key|
    result[yield(key)] = self[key]
  end
  result
end

#transform_keys!Object

Destructively convert all keys using the block operations. Same as transform_keys but modifies self.



21
22
23
24
25
26
# File 'lib/chozo/core_ext/hash/keys.rb', line 21

def transform_keys!
  keys.each do |key|
    self[yield(key)] = delete(key)
  end
  self
end