class Hash

Public Instance Methods

extract(*ks) click to toggle source

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

@example Key order does not matter

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

@example Missing keys are ignored

hash.extract(:a, :d) #=> { a: 1}
# File lib/shenanigans/hash/extract.rb, line 9
def extract(*ks)
  existing = keys & ks
  Hash[existing.zip(values_at(*existing))]
end
has_shape?(shape) click to toggle source

Checks if a hash has a certain structure.

@example Simple hash

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

@example Nested hashes

h = { k1: [], k2: { k3: Struct.new("Foo") } }
shape = { k1: Array, k2: { k3: Module } }
h.has_shape?(shape) #=> true
# File lib/shenanigans/hash/has_shape_pred.rb, line 12
def has_shape?(shape)
  all? do |k, v|
    Hash === v ? v.has_shape?(shape[k]) : shape[k] === v
  end
end
to_ostruct() click to toggle source

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

@example

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"
# File lib/shenanigans/hash/to_ostruct.rb, line 22
def to_ostruct
  arr = map { |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
  }
  OpenStruct.new(Hash[arr])
end