module Evil::Struct::Utils

Collection of utility methods to hashify and merge structures

Public Instance Methods

hashify(value) click to toggle source

Converts value to nested hash

Makes conversion through nested hashes, arrays, enumerables, and other objects that respond to `to_a`, `to_h`, `to_hash`, or `each`. Doesn't convert `nil` (even though it responds to `to_h` and `to_a`).

@param [Object] value @return [Hash]

# File lib/evil/struct/utils.rb, line 14
def hashify(value)
  hash = to_h(value)
  list = to_a(value)

  if hash
    hash.each_with_object({}) { |(key, val), obj| obj[key] = hashify(val) }
  elsif list
    list.map { |item| hashify(item) }
  else
    value
  end
end
merge(source, target) click to toggle source

Shallowly merges target object to the source hash

The target object can be hash, or respond to either `to_h`, or `to_hash`. Before a merge, the keys of the target object are symbolized.

@param [Hash<Symbol, Object>] source @param [Hash, to_h, to_hash] target @return [Hash<Symbol, Object>]

# File lib/evil/struct/utils.rb, line 36
def merge(source, target)
  source.merge(to_h(target))
end
merge_deeply(source, target) click to toggle source

Deeply merges target object to the source one

The nesting stops when a first non-hashified value reached. It do not merge arrays of hashes!

@param [Object] source @param [Object] target @return [Object]

# File lib/evil/struct/utils.rb, line 49
def merge_deeply(source, target)
  source_hash = to_h(source)
  target_hash = to_h(target)
  return target unless source_hash && target_hash

  keys = (source_hash.keys | target_hash.keys)
  keys.each_with_object(source_hash) do |key, obj|
    next unless target_hash.key? key
    obj[key] = merge_deeply source_hash[key], target_hash[key]
  end
end

Private Instance Methods

to_a(value) click to toggle source
# File lib/evil/struct/utils.rb, line 78
def to_a(value)
  if    value.is_a? Array       then value
  elsif value.is_a? Hash        then nil
  elsif value.nil?              then nil
  elsif value.respond_to? :to_a then value.to_a
  end
end
to_h(value) click to toggle source
# File lib/evil/struct/utils.rb, line 63
def to_h(value)
  to_hash(value)&.each_with_object({}) do |(key, val), obj|
    obj[key.to_sym] = val
  end
end
to_hash(value) click to toggle source
# File lib/evil/struct/utils.rb, line 69
def to_hash(value)
  if    value.is_a? Hash           then value
  elsif value.is_a? Array          then nil
  elsif value.nil?                 then nil
  elsif value.respond_to? :to_h    then value.to_h
  elsif value.respond_to? :to_hash then value.to_hash
  end
end