Class: SleepingKingStudios::Tools::HashTools

Inherits:
Base
  • Object
show all
Defined in:
lib/sleeping_king_studios/tools/hash_tools.rb

Overview

Tools for working with hash-like enumerable objects.

Constant Summary collapse

HASH_METHODS =

Expected methods that a Hash-like object should implement.

%i[[] count each each_key each_pair].freeze

Instance Method Summary collapse

Methods inherited from Base

#initialize, instance, #toolbelt

Constructor Details

This class inherits a constructor from SleepingKingStudios::Tools::Base

Instance Method Details

#convert_keys_to_strings(hsh) ⇒ Hash Also known as: stringify_keys

Returns a deep copy of the hash with the keys converted to strings.

Examples:

hsh = { :one => 1, :two => 2, :three => 3 }
cpy = HashTools.convert_keys_to_strings(hsh)
#=> { 'one' => 1, 'two' => 2, 'three' => 3 }
hsh
#=> { :one => 1, :two => 2, :three => 3 }

hsh = { :odd => { :one => 1, :three => 3 }, :even => { :two => 2, :four => 4 } }
cpy = HashTools.convert_keys_to_strings(hsh)
#=> { 'odd' => { 'one' => 1, 'three' => 3 }, 'even' => { 'two' => 2, 'four' => 4 } }
hsh
#=> { :odd => { :one => 1, :three => 3 }, :even => { :two => 2, :four => 4 } }

Parameters:

  • hsh (Hash)

    the hash to convert.

Returns:

  • (Hash)

    the converted copy of the hash.

Raises:

  • (ArgumentError)

    if the first argument is not an Hash-like object.



46
47
48
49
50
51
52
53
54
# File 'lib/sleeping_king_studios/tools/hash_tools.rb', line 46

def convert_keys_to_strings(hsh)
  require_hash!(hsh)

  hsh.each.with_object({}) do |(key, value), cpy|
    sym = key.to_s

    cpy[sym] = convert_value_to_stringified_hash(value)
  end
end

#convert_keys_to_symbols(hsh) ⇒ Hash Also known as: symbolize_keys

Returns a deep copy of the hash with the keys converted to symbols.

Examples:

hsh = { 'one' => 1, 'two' => 2, 'three' => 3 }
cpy = HashTools.convert_keys_to_symbols(hsh)
#=> { :one => 1, :two => 2, :three => 3 }
hsh
#=> { 'one' => 1, 'two' => 2, 'three' => 3 }

hsh = { 'odd' => { 'one' => 1, 'three' => 3 }, 'even' => { 'two' => 2, 'four' => 4 } }
cpy = HashTools.convert_keys_to_strings(hsh)
#=> { :odd => { :one => 1, :three => 3 }, :even => { :two => 2, :four => 4 } }
hsh
#=> { 'odd' => { 'one' => 1, 'three' => 3 }, 'even' => { 'two' => 2, 'four' => 4 } }

Parameters:

  • hsh (Hash)

    the hash to convert.

Returns:

  • (Hash)

    the converted copy of the hash.

Raises:

  • (ArgumentError)

    if the first argument is not an Hash-like object.



77
78
79
80
81
82
83
84
85
# File 'lib/sleeping_king_studios/tools/hash_tools.rb', line 77

def convert_keys_to_symbols(hsh)
  require_hash!(hsh)

  hsh.each.with_object({}) do |(key, value), cpy|
    sym = key.to_s.intern

    cpy[sym] = convert_value_to_symbolic_hash(value)
  end
end

#deep_dup(hsh) ⇒ Hash

Creates a deep copy of the Hash.

Examples:

hsh = { :one => 'one', :two => 'two', :three => 'three' }
cpy = HashTools.deep_dup hsh

cpy.update :four => 'four'
#=> { :one => 'one', :two => 'two', :three => 'three', :four => 'four' }
hsh
#=> { :one => 'one', :two => 'two', :three => 'three' }

cpy[:one].sub!(/on/, 'vu'); cpy
#=> { :one => 'vun', :two => 'two', :three => 'three', :four => 'four' }
hsh
#=> { :one => 'one', :two => 'two', :three => 'three' }

Parameters:

  • hsh (Hash)

    the hash to copy.

Returns:

  • (Hash)

    the copy of the hash.

Raises:

  • (ArgumentError)

    if the first argument is not an Hash-like object.



109
110
111
112
113
114
115
116
117
# File 'lib/sleeping_king_studios/tools/hash_tools.rb', line 109

def deep_dup(hsh)
  require_hash!(hsh)

  object_tools = toolbelt.object_tools

  hsh.each.with_object({}) do |(key, value), copy|
    copy[object_tools.deep_dup key] = object_tools.deep_dup(value)
  end
end

#deep_freeze(hsh) ⇒ Hash

Freezes the hash and performs a deep freeze on each hash key and value.

Examples:

hsh = { :one => 'one', :two => 'two', :three => 'three' }
HashTools.deep_freeze hsh

hsh.frozen?
#=> true
hsh[:one].frozen?
#=> true

Parameters:

  • hsh (Hash)

    the hash to freeze.

Returns:

  • (Hash)

    the frozen hash.

Raises:

  • (ArgumentError)

    if the first argument is not an Hash-like object.



135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/sleeping_king_studios/tools/hash_tools.rb', line 135

def deep_freeze(hsh)
  require_hash!(hsh)

  hsh.freeze

  object_tools = toolbelt.object_tools

  hsh.each do |key, value|
    object_tools.deep_freeze key
    object_tools.deep_freeze value
  end
end

#fetch(hsh, key, default = nil, indifferent_key: false) ⇒ Object #fetch(hsh, key, indifferent_key: false) {|key| ... } ⇒ Object

Overloads:

  • #fetch(hsh, key, default = nil, indifferent_key: false) ⇒ Object

    Retrieves the value at the specified key.

    If the value does not exist, returns the default value, or raises a KeyError if there is no default value. If the object defines a native #fetch method, delegates to the native implementation.

    Parameters:

    • hsh (Hash)

      the hash or hash-like object.

    • key (Object)

      the key to retrieve.

    • indifferent_key (true, false) (defaults to: false)

      if true and the key is a String or a Symbol, tries to match both the String and Symbol equivalent. Defaults to false.

    • default (Object) (defaults to: nil)

      the default value.

    Returns:

    • (Object)

      the value at the specified key.

    Raises:

    • (KeyError)

      if the hash does not have a value at that key and there is no default value.

  • #fetch(hsh, key, indifferent_key: false) {|key| ... } ⇒ Object

    Retrieves the value at the specified key.

    If the value does not exist, returns the value of the default block, or raises a KeyError if there is no default block. If the object defines a native #fetch method, delegates to the native implementation.

    Parameters:

    • hsh (Hash)

      the hash or hash-like object.

    • key (Object)

      the key to retrieve.

    • indifferent_key (true, false) (defaults to: false)

      if true and the key is a String or a Symbol, tries to match both the String and Symbol equivalent. Defaults to false.

    Yields:

    • generates the default value if there is no value at the key.

    Yield Parameters:

    • key (Object)

      the requested key.

    Yield Returns:

    • (Object)

      the default value.

    Returns:

    • (Object)

      the value at the specified key.

    Raises:

    • (KeyError)

      if the hash does not have a value at that key and there is no default value.

Raises:

  • (KeyError)


190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/sleeping_king_studios/tools/hash_tools.rb', line 190

def fetch(hsh, key, default = UNDEFINED, indifferent_key: false, &block) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
  require_hash!(hsh)

  if hsh.respond_to?(:fetch)
    return native_fetch(hsh, key, default, indifferent_key:, &block)
  end

  return hsh[key] if hsh.key?(key)

  if indifferent_key && (key.is_a?(String) || key.is_a?(Symbol))
    indifferent_key = key.is_a?(String) ? key.to_sym : key.to_s

    return hsh[indifferent_key] if hsh.key?(indifferent_key)
  end

  return block.call(key) if block_given?

  return default unless default == UNDEFINED

  raise KeyError, "key not found: #{key.inspect}"
end

#generate_binding(hsh) ⇒ Binding

Generates a Binding with the hash values as local variables.

This method is primarily used when rendering ERB templates.

Examples:

hsh     = { :one => 'one', :two => 'two', :three => 'three' }
binding = HashTools.generate_binding(hsh)
#=> Binding

binding.local_variable_defined?(:one)
#=> true
binding.local_variable_get(:one)
#=> 'one'
binding.eval('one')
#=> 'one'

Returns:

  • (Binding)

    the binding object.

Raises:

  • (ArgumentError)

    if the first argument is not an Hash-like object.



231
232
233
234
235
236
237
238
239
# File 'lib/sleeping_king_studios/tools/hash_tools.rb', line 231

def generate_binding(hsh)
  require_hash!(hsh)

  toolbelt.core_tools.empty_binding.tap do |binding|
    hsh.each do |key, value|
      binding.local_variable_set key, value
    end
  end
end

#hash?(obj) ⇒ Boolean

Returns true if the object is or appears to be a Hash.

This method checks for the method signatures of the object. A Hash-like method will define all of the the #[], #count, #each, #each_key, and #each_value methods.

Examples:

HashTools.hash?(nil)
#=> false
HashTools.hash?([])
#=> false
HashTools.hash?({})
#=> true

Parameters:

  • obj (Object)

    the object to test.

Returns:

  • (Boolean)

    true if the object is a Hash, otherwise false.



258
259
260
261
262
263
264
265
266
# File 'lib/sleeping_king_studios/tools/hash_tools.rb', line 258

def hash?(obj)
  return true if obj.is_a?(Hash)

  HASH_METHODS.each do |method_name|
    return false unless obj.respond_to?(method_name)
  end

  true
end

#immutable?(hsh) ⇒ Boolean

Returns true if the hash is immutable.

A hash is considered immutable if the hash itself is frozen and each key and value in the hash is immutable.

Examples:

HashTools.immutable?({ :id => 0, :title => 'The Ramayana' })
#=> false

HashTools.immutable?({ :id => 0, :title => +'The Ramayana' }.freeze)
#=> false

HashTools.immutable?({ :id => 0, :title => 'The Ramayana' }.freeze)
#=> true

Parameters:

  • hsh (Hash)

    the hash to test.

Returns:

  • (Boolean)

    true if the hash is immutable, otherwise false.

Raises:

  • (ArgumentError)

    if the first argument is not an Hash-like object.

See Also:



292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'lib/sleeping_king_studios/tools/hash_tools.rb', line 292

def immutable?(hsh)
  require_hash!(hsh)

  return false unless hsh.frozen?

  object_tools = toolbelt.object_tools

  hsh.each do |key, value|
    unless object_tools.immutable?(key) && object_tools.immutable?(value)
      return false
    end
  end

  true
end

#mutable?(hsh) ⇒ Boolean

Returns true if the hash or any of its contents are mutable.

Parameters:

  • hsh (Hash)

    the hash to test.

Returns:

  • (Boolean)

    true if the hash is mutable, otherwise false.

Raises:

  • (ArgumentError)

    if the first argument is not an Hash-like object.

See Also:



317
318
319
# File 'lib/sleeping_king_studios/tools/hash_tools.rb', line 317

def mutable?(hsh)
  !immutable?(hsh)
end