Class: Hash

Inherits:
Object show all
Defined in:
lib/shenanigans/hash/extract.rb,
lib/shenanigans/hash/to_ostruct.rb,
lib/shenanigans/hash/has_shape_pred.rb

Instance Method Summary collapse

Instance Method Details

#extract(*ks) ⇒ Object

Returns a new hash only with the specified keys (if present).

hash = { a: 1, b: 2, c: 3 }
hash.extract(:b, :a)
#=> { a: 1, b: 2 }
hash.extract(:a, :d)
#=> { a: 1}

8
9
10
11
# File 'lib/shenanigans/hash/extract.rb', line 8

def extract(*ks)
  existing = keys & ks
  Hash[existing.zip(values_at(*existing))]
end

#has_shape?(shape) ⇒ Boolean

Checks if a hash has a certain structure.

h = { k1: 1, k2: "1" }
h.has_shape?(k1: Fixnum, k2: String)
#=> true
h.has_shape?(k1: Class, k2: String)
#=> false

It also works with compound data structures.

h = { k1: [], k2: { k3: Struct.new("Foo") } }
shape = { k1: Array, k2: { k3: Module } }
h.has_shape?(shape)
#=> true

Returns:

  • (Boolean)

13
14
15
16
17
# File 'lib/shenanigans/hash/has_shape_pred.rb', line 13

def has_shape?(shape)
  all? do |k, v|
    Hash === v ? v.has_shape?(shape[k]) : shape[k] === v
  end
end

#to_ostructObject

Recursively converts a Hash and all nested Hashes to OpenStructs. Especially useful for parsing YAML.

yaml=<<EOY
subject: Programming Languages
languages:
  - name        : Ruby
    creator     : Matz
  - name        : Python
    creator     : Guido van Rossum
  - name        : Perl
    creator     : Larry Wall
EOY
struct = YAML.load(yaml).to_ostruct
struct.subject
#=> "Programming Languages"
struct.languages.first
#=> #<OpenStruct name="Ruby", creator="Matz">
struct.languages.first.creator
#=> "Matz"

23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/shenanigans/hash/to_ostruct.rb', line 23

def to_ostruct
  arr = map do |k, v|
    case v
    when Hash
      [k, v.to_ostruct]
    when Array
      [k, v.map { |el| el.respond_to?(:to_ostruct) ? el.to_ostruct : el }]
    else
      [k, v]
    end
  end
  OpenStruct.new(Hash[arr])
end