Class: Builderator::Config::Rash

Inherits:
Hash
  • Object
show all
Defined in:
lib/builderator/config/rash.rb

Overview

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

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(from = {}, seal = false) ⇒ Rash

Returns a new instance of Rash.



22
23
24
25
26
27
28
29
# 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

Instance Attribute Details

#sealedObject

Returns the value of attribute sealed.



20
21
22
# File 'lib/builderator/config/rash.rb', line 20

def sealed
  @sealed
end

Class Method Details

.coerce(somehting) ⇒ Object



11
12
13
14
15
16
17
# 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

Instance Method Details

#cloneObject



31
32
33
# File 'lib/builderator/config/rash.rb', line 31

def clone
  self.class.new(self, sealed)
end

#diff(other) ⇒ Object



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# 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) ⇒ Boolean

Returns:

  • (Boolean)


44
45
46
# File 'lib/builderator/config/rash.rb', line 44

def has?(key, klass = BasicObject)
  include?(key) && fetch(key).is_a?(klass)
end

#mObject

Symbolize keys



49
50
51
52
53
# File 'lib/builderator/config/rash.rb', line 49

[:include?, :[], :fetch, :[]=, :store].each do |m|
  define_method(m) do |key, *args|
    super(key.to_sym, *args)
  end
end

#merge!(other) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# 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) ⇒ Object



35
36
37
38
# 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_hashObject



122
123
124
125
126
127
128
129
130
# 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

#unsealObject



40
41
42
# File 'lib/builderator/config/rash.rb', line 40

def unseal
  seal(false)
end