Class: Hanami::Utils::Hash

Inherits:
Object
  • Object
show all
Extended by:
Transproc::Registry
Defined in:
gems/gems/hanami-utils-1.3.0/lib/hanami/utils/hash.rb

Overview

Hash on steroids rubocop:disable ClassLength

Since:

  • 0.1.0

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(hash = {}, &blk) ⇒ Hanami::Utils::Hash

Deprecated.

Initialize the hash

Examples:

Passing a Hash

require 'hanami/utils/hash'

hash = Hanami::Utils::Hash.new('l' => 23)
hash['l'] # => 23

Passing a block for default

require 'hanami/utils/hash'

hash = Hanami::Utils::Hash.new {|h,k| h[k] = [] }
hash['foo'].push 'bar'

hash.to_h # => { 'foo' => ['bar'] }

Parameters:

  • hash (#to_h) (defaults to: {})

    the value we want to use to initialize this instance

  • blk (Proc)

    define the default value

See Also:

Since:

  • 0.1.0

def initialize(hash = {}, &blk)
  @hash = hash.to_hash
  @hash.default_proc = blk if blk
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args, &blk) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Override Ruby's method_missing in order to provide ::Hash interface

Raises:

  • (NoMethodError)

    If doesn't respond to the given method

Since:

  • 0.3.0

def method_missing(method_name, *args, &blk)
  raise NoMethodError.new(%(undefined method `#{method_name}' for #{@hash}:#{self.class})) unless respond_to?(method_name)

  h = @hash.__send__(method_name, *args, &blk)
  h = self.class.new(h) if h.is_a?(::Hash)
  h
end

Class Method Details

.deep_dup(input) ⇒ ::Hash

Deep duplicate hash values

The output of this function is a shallow duplicate of the input. Any further modification on the input, won't be reflected on the output and viceversa.

Examples:

Basic Usage

require 'hanami/utils/hash'

input  = { "a" => { "b" => { "c" => [1, 2, 3] } } }
output = Hanami::Utils::Hash.deep_dup(input)
  # => {"a"=>{"b"=>{"c"=>[1,2,3]}}}

output.class
  # => Hash

# mutations on input aren't reflected on output

input["a"]["b"]["c"] << 4
output.dig("a", "b", "c")
  # => [1, 2, 3]

# mutations on output aren't reflected on input

output["a"].delete("b")
input
  # => {"a"=>{"b"=>{"c"=>[1,2,3,4]}}}

Parameters:

  • input (::Hash)

    the input

Returns:

  • (::Hash)

    the shallow duplicate of input

Since:

  • 1.0.1

def self.deep_dup(input)
  input.each_with_object({}) do |(k, v), result|
    result[k] = case v
                when ::Hash
                  deep_dup(v)
                else
                  Duplicable.dup(v)
                end
  end
end

.deep_serialize(input) ⇒ ::Hash

Deep serialize given object into a Hash

Please note that the returning Hash will use symbols as keys.

Examples:

Basic Usage

require 'hanami/utils/hash'
require 'ostruct'

class Data < OpenStruct
  def to_hash
    to_h
  end
end

input = Data.new("foo" => "bar", baz => [Data.new(hello: "world")])

Hanami::Utils::Hash.deep_serialize(input)
  # => {:foo=>"bar", :baz=>[{:hello=>"world"}]}

Parameters:

Returns:

  • (::Hash)

    the deep serialized hash

Since:

  • 1.1.0

def self.deep_serialize(input) # rubocop:disable Metrics/MethodLength
  input.to_hash.each_with_object({}) do |(key, value), output|
    output[key.to_sym] =
      case value
      when ->(h) { h.respond_to?(:to_hash) }
        deep_serialize(value)
      when Array
        value.map do |item|
          item.respond_to?(:to_hash) ? deep_serialize(item) : item
        end
      else
        value
      end
  end
end

.deep_stringify(input) ⇒ ::Hash

Deeply stringify the given hash

Examples:

Basic Usage

require "hanami/utils/hash"

hash = Hanami::Utils::Hash.deep_stringify(foo: "bar", baz: {a: 1})
  # => {"foo"=>"bar", "baz"=>{"a"=>1}}

hash.class
  # => Hash

Parameters:

  • input (::Hash)

    the input

Returns:

  • (::Hash)

    the deep stringified hash

Since:

  • 1.1.1

def self.deep_stringify(input) # rubocop:disable Metrics/MethodLength
  input.each_with_object({}) do |(key, value), output|
    output[key.to_s] =
      case value
      when ::Hash
        deep_stringify(value)
      when Array
        value.map do |item|
          item.is_a?(::Hash) ? deep_stringify(item) : item
        end
      else
        value
      end
  end
end

.deep_symbolize(input) ⇒ ::Hash

Deep symbolize the given hash

Examples:

Basic Usage

require 'hanami/utils/hash'

hash = Hanami::Utils::Hash.deep_symbolize("foo" => "bar", "baz" => {"a" => 1})
  # => {:foo=>"bar", :baz=>{a:=>1}}

hash.class
  # => Hash

Parameters:

  • input (::Hash)

    the input

Returns:

  • (::Hash)

    the deep symbolized hash

See Also:

Since:

  • 1.0.1

def self.deep_symbolize(input)
  self[:deep_symbolize_keys].call(input)
end

.stringify(input) ⇒ ::Hash

Stringify the given hash

Examples:

Basic Usage

require 'hanami/utils/hash'

hash = Hanami::Utils::Hash.stringify(foo: "bar", baz: {a: 1})
  # => {"foo"=>"bar", "baz"=>{:a=>1}}

hash.class
  # => Hash

Parameters:

  • input (::Hash)

    the input

Returns:

  • (::Hash)

    the stringified hash

Since:

  • 1.0.1

def self.stringify(input)
  self[:stringify_keys].call(input)
end

.symbolize(input) ⇒ ::Hash

Symbolize the given hash

Examples:

Basic Usage

require 'hanami/utils/hash'

hash = Hanami::Utils::Hash.symbolize("foo" => "bar", "baz" => {"a" => 1})
  # => {:foo=>"bar", :baz=>{"a"=>1}}

hash.class
  # => Hash

Parameters:

  • input (::Hash)

    the input

Returns:

  • (::Hash)

    the symbolized hash

See Also:

Since:

  • 1.0.1

def self.symbolize(input)
  self[:symbolize_keys].call(input)
end

Instance Method Details

#==(other) ⇒ TrueClass, FalseClass Also known as: eql?

Deprecated.

Equality

Returns:

  • (TrueClass, FalseClass)

Since:

  • 0.3.0

def ==(other)
  @hash == other.to_h
end

#[](key) ⇒ Object?

Deprecated.

Retrieves the value object corresponding to the key object.

Parameters:

  • key (Object)

    the key

Returns:

  • (Object, nil)

    the correspoding value, if present

See Also:

Since:

  • 0.3.0

def [](key)
  @hash[key]
end

#[]=(key, value) ⇒ Object

Deprecated.

Associates the value given by value with the key given by key.

Parameters:

  • key (Object)

    the key to assign

  • value (Object)

    the value to assign

See Also:

Since:

  • 0.3.0

def []=(key, value)
  @hash[key] = value
end

#deep_dupHash

Deprecated.

Use deep_dup

Return a deep copy of the current Hanami::Utils::Hash

Examples:

require 'hanami/utils/hash'

hash = Hanami::Utils::Hash.new(
  'nil'        => nil,
  'false'      => false,
  'true'       => true,
  'symbol'     => :foo,
  'fixnum'     => 23,
  'bignum'     => 13289301283 ** 2,
  'float'      => 1.0,
  'complex'    => Complex(0.3),
  'bigdecimal' => BigDecimal('12.0001'),
  'rational'   => Rational(0.3),
  'string'     => 'foo bar',
  'hash'       => { a: 1, b: 'two', c: :three },
  'u_hash'     => Hanami::Utils::Hash.new({ a: 1, b: 'two', c: :three })
)

duped = hash.deep_dup

hash.class  # => Hanami::Utils::Hash
duped.class # => Hanami::Utils::Hash

hash.object_id  # => 70147385937100
duped.object_id # => 70147385950620

# unduplicated values
duped['nil']        # => nil
duped['false']      # => false
duped['true']       # => true
duped['symbol']     # => :foo
duped['fixnum']     # => 23
duped['bignum']     # => 176605528590345446089
duped['float']      # => 1.0
duped['complex']    # => (0.3+0i)
duped['bigdecimal'] # => #<BigDecimal:7f9ffe6e2fd0,'0.120001E2',18(18)>
duped['rational']   # => 5404319552844595/18014398509481984)

# it duplicates values
duped['string'].reverse!
duped['string'] # => "rab oof"
hash['string']  # => "foo bar"

# it deeply duplicates Hash, by preserving the class
duped['hash'].class # => Hash
duped['hash'].delete(:a)
hash['hash'][:a]    # => 1

duped['hash'][:b].upcase!
duped['hash'][:b] # => "TWO"
hash['hash'][:b]  # => "two"

# it deeply duplicates Hanami::Utils::Hash, by preserving the class
duped['u_hash'].class # => Hanami::Utils::Hash

Returns:

  • (Hash)

    a deep duplicated self

Since:

  • 0.3.1

def deep_dup
  self.class.new.tap do |result|
    @hash.each { |k, v| result[k] = Duplicable.dup(v, &DUPLICATE_LOGIC) }
  end
end

#deep_symbolize!Hash

Deprecated.

Convert in-place all the keys to Symbol instances, nested hashes are converted too.

Examples:

require 'hanami/utils/hash'

hash = Hanami::Utils::Hash.new 'a' => 23, 'b' => { 'c' => ['x','y','z'] }
hash.deep_symbolize!

hash.keys    # => [:a, :b]
hash.inspect # => {:a=>23, :b=>{:c=>["x", "y", "z"]}}

Returns:

Since:

  • 1.0.0

def deep_symbolize!
  keys.each do |k|
    v = delete(k)
    v = self.class.new(v).deep_symbolize! if v.respond_to?(:to_hash)

    self[k.to_sym] = v
  end

  self
end

#delete(key) ⇒ Object?

Deprecated.

Deletes the key-value pair and returns the value from hsh whose key is equal to key.

Parameters:

  • key (Object)

    the key to remove

Returns:

  • (Object, nil)

    the value hold by the given key, if present

See Also:

Since:

  • 0.3.0

def delete(key)
  @hash.delete(key)
end

#hashFixnum

Deprecated.

Returns the hash of the internal @hash

Returns:

  • (Fixnum)

Since:

  • 0.3.0

def hash
  @hash.hash
end

#inspectString

Deprecated.

Returns a string describing the internal @hash

Returns:

Since:

  • 0.3.0

def inspect
  @hash.inspect
end

#keysArray

Deprecated.

Returns a new array populated with the keys from this hash

Returns:

  • (Array)

    the keys

See Also:

Since:

  • 0.3.0

def keys
  @hash.keys
end

#stringify!Hash

Deprecated.

Use stringify

Convert in-place all the keys to Symbol instances, nested hashes are converted too.

Examples:

require 'hanami/utils/hash'

hash = Hanami::Utils::Hash.new a: 23, b: { c: ['x','y','z'] }
hash.stringify!

hash.keys    # => [:a, :b]
hash.inspect # => {"a"=>23, "b"=>{"c"=>["x", "y", "z"]}}

Returns:

Since:

  • 0.3.2

def stringify!
  keys.each do |k|
    v = delete(k)
    v = self.class.new(v).stringify! if v.respond_to?(:to_hash)

    self[k.to_s] = v
  end

  self
end

#symbolize!Hash

Deprecated.

Use symbolize

Convert in-place all the keys to Symbol instances.

Examples:

require 'hanami/utils/hash'

hash = Hanami::Utils::Hash.new 'a' => 23, 'b' => { 'c' => ['x','y','z'] }
hash.symbolize!

hash.keys    # => [:a, :b]
hash.inspect # => { :a => 23, :b => { 'c' => ["x", "y", "z"] } }

Returns:

Since:

  • 0.1.0

def symbolize!
  keys.each do |k|
    v = delete(k)
    self[k.to_sym] = v
  end

  self
end

#to_a::Array

Deprecated.

Converts into a nested array of [ key, value ] arrays.

Returns:

  • (::Array)

    the array

See Also:

Since:

  • 0.3.0

def to_a
  @hash.to_a
end

#to_h::Hash Also known as: to_hash

Deprecated.

Returns a Ruby Hash as duplicated version of self

Returns:

  • (::Hash)

    the hash

See Also:

Since:

  • 0.3.0

def to_h
  @hash.each_with_object({}) do |(k, v), result|
    v = v.to_h if v.respond_to?(:to_hash)
    result[k] = v
  end
end