class Builderator::Config::Rash

A self-populating sparse Hash by Rapid7 ([R]apid7 h). Definetly not a Mash or Smash…

Attributes

sealed[RW]

Public Class Methods

coerce(somehting) click to toggle source
# File lib/builderator/config/rash.rb, line 11
def coerce(somehting)
  return somehting if somehting.is_a?(self)
  return new(somehting) if somehting.is_a?(Hash)

  ## `somehting` is not a valid input. Just give back an instance.
  new
end
new(from = {}, seal = false) click to toggle source
Calls superclass method
# File lib/builderator/config/rash.rb, line 22
def initialize(from = {}, seal = false)
  @sealed = seal
  super() do |_, k|
    self[k] = self.class.new unless sealed
  end

  merge!(from) ## Clone a Rash or coerce a Hash to a new Rash
end

Public Instance Methods

clone() click to toggle source
# File lib/builderator/config/rash.rb, line 31
def clone
  self.class.new(self, sealed)
end
diff(other) click to toggle source
# File lib/builderator/config/rash.rb, line 88
def diff(other)
  fail TypeError, 'Argument other of `Rash#diff(other)` must be a Hash.'\
                  " Recieved #{other.class}" unless other.is_a?(Hash)

  other.each_with_object({}) do |(k, v), diff|
    next if has?(k) && self[k] == v

    ## Merge Arrays
    if v.is_a?(Array)
      a = has?(k) ? Config::List.coerce(self[k]) : Config::List.new
      b = Config::List.coerce(v)

      diff[k] = {
        :+ => b - a,
        :- => a - b
      }

      next
    end

    ## Overwrite non-Hash values
    unless v.is_a?(Hash)
      diff[k] = {
        :+ => v,
        :- => fetch(k, nil)
      }

      next
    end

    diff[k] = self.class.coerce(fetch(k, {})).diff(self.class.coerce(v))
  end
end
has?(key, klass = BasicObject) click to toggle source
# File lib/builderator/config/rash.rb, line 44
def has?(key, klass = BasicObject)
  include?(key) && fetch(key).is_a?(klass)
end
merge!(other) click to toggle source
# File lib/builderator/config/rash.rb, line 55
def merge!(other)
  fail TypeError, 'Argument other of  `Rash#merge!(other)` must be a Hash.'\
                  " Recieved #{other.class}" unless other.is_a?(Hash)

  other.each_with_object({}) do |(k, v), diff|
    ## Replace `-`s with `_`s in in String keys
    k = k.gsub(/\-/, '_').to_sym if k.is_a?(String)

    next if has?(k) && self[k] == v

    ## Merge Arrays
    if v.is_a?(Array)
      self[k] = has?(k) ? Config::List.coerce(self[k]) : Config::List.new
      self[k].merge!(v)

      diff[k] = true
      next
    end

    ## Overwrite non-Hash values
    unless v.is_a?(Hash)
      self[k] = v

      diff[k] = true
      next
    end

    ## Merge recursivly coerces `v` to a Rash
    self[k] = self.class.coerce(self[k])
    diff[k] = self[k].merge!(v)
  end
end
seal(action = true) click to toggle source
# File lib/builderator/config/rash.rb, line 35
def seal(action = true)
  @sealed = action
  each_value { |v| v.seal(action) if v.is_a?(self.class) }
end
to_hash() click to toggle source
# File lib/builderator/config/rash.rb, line 122
def to_hash
  each_with_object({}) do |(k, v), hash|
    ## Not a hash-value
    next hash[k] = v unless v.is_a?(self.class)

    ## Recursivly coerces `v` to a Hash
    hash[k] = v.to_hash
  end
end
unseal() click to toggle source
# File lib/builderator/config/rash.rb, line 40
def unseal
  seal(false)
end