Class: AttributeStruct

Inherits:
BasicObject
Defined in:
lib/attribute_struct/version.rb,
lib/attribute_struct/attribute_hash.rb,
lib/attribute_struct/attribute_struct.rb

Defined Under Namespace

Classes: AttributeHash, Version

Constant Summary collapse

VERSION =
Version.new('0.1.8')

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args, &block) ⇒ AttributeStruct

Returns a new instance of AttributeStruct.



49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/attribute_struct/attribute_struct.rb', line 49

def initialize(*args, &block)
  _klass.load_the_hash
  @_camel_keys = _klass.camel_keys
  @table = __hashish.new
  unless(args.empty?)
    if(args.size == 1 && args.first.is_a?(::Hash))
      _load(args.first)
    end
  end
  if(block)
    self.instance_exec(&block)
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(sym, *args, &block) ⇒ Object

Dragons and unicorns all over in here



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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/attribute_struct/attribute_struct.rb', line 89

def method_missing(sym, *args, &block)
  if((s = sym.to_s).end_with?('='))
    s.slice!(-1, s.length)
    sym = s
  end
  sym = _process_key(sym)
  @table[sym] ||= _klass_new
  if(!args.empty? || block)
    if(args.empty? && block)
      base = @table[sym]
      if(block.arity == 0)
        base.instance_exec(&block)
      else
        base.instance_exec(base, &block)
      end
      @table[sym] = base
    elsif(!args.empty? && block)
      base = @table[sym]
      base = _klass_new unless base.is_a?(_klass)
      @table[sym] = base
      leaf = base
      args.each do |arg|
        leaf = base[arg]
        unless(leaf.is_a?(_klass))
          leaf = _klass_new
          base._set(arg, leaf)
          base = leaf
        end
      end
      if(block.arity == 0)
        leaf.instance_exec(&block)
      else
        leaf.instance_exec(leaf, &block)
      end
    else
      if(args.size > 1)
        @table[sym] = _klass_new unless @table[sym].is_a?(_klass)
        endpoint = args.inject(@table[sym]) do |memo, k|
          unless(memo[k].is_a?(_klass))
            memo._set(k, _klass_new)
          end
          memo[k]
        end
        return endpoint # custom break out
      else
        @table[sym] = args.first
      end
    end
  end
  @table[sym]
end

Class Attribute Details

.camel_keysObject

Global flag for camel cased keys



6
7
8
# File 'lib/attribute_struct/attribute_struct.rb', line 6

def camel_keys
  @camel_keys
end

.force_chefObject

Force tooling from Chef



8
9
10
# File 'lib/attribute_struct/attribute_struct.rb', line 8

def force_chef
  @force_chef
end

Instance Attribute Details

#_camel_keysObject

Flag for camel cased keys



47
48
49
# File 'lib/attribute_struct/attribute_struct.rb', line 47

def _camel_keys
  @_camel_keys
end

Class Method Details

.hashishObject



39
40
41
42
# File 'lib/attribute_struct/attribute_struct.rb', line 39

def hashish
  load_the_hash
  @hash_loaded == :chef ? ::Mash : ::AttributeStruct::AttributeHash
end

.load_the_camelsObject

Loads helpers for camel casing



18
19
20
21
22
23
# File 'lib/attribute_struct/attribute_struct.rb', line 18

def load_the_camels
  unless(@camels_loaded)
    require 'attribute_struct/monkey_camels'
    @camels_loaded = true
  end
end

.load_the_hashObject

Determines what hash library to load based on availability



26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/attribute_struct/attribute_struct.rb', line 26

def load_the_hash
  unless(@hash_loaded)
    if(defined?(Chef) || force_chef)
      require 'chef/mash'
      require 'chef/mixin/deep_merge'
      @hash_loaded = :chef
    else
      require 'attribute_struct/attribute_hash'
      @hash_loaded = :attribute_hash
    end
  end
end

Instance Method Details

#[](key) ⇒ Object

key

Object

Access data directly



72
73
74
# File 'lib/attribute_struct/attribute_struct.rb', line 72

def [](key)
  _data[_process_key(key)]
end

#__hashishObject

Returns a new Hash type instance based on what is available



239
240
241
# File 'lib/attribute_struct/attribute_struct.rb', line 239

def __hashish
  defined?(::Chef) ? ::Mash : ::AttributeStruct::AttributeHash
end

#_array(*args) ⇒ Object

args

Objects

Helper to create Arrays with nested AttributeStructs. Proc instances are automatically executed into new AttributeStruct instances



337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
# File 'lib/attribute_struct/attribute_struct.rb', line 337

def _array(*args)
  args.map do |maybe_block|
    if(maybe_block.is_a?(::Proc))
      klass = _klass_new
      if(maybe_block.arity > 0)
        klass.instance_exec(klass, &maybe_block)
      else
        klass.instance_exec(&maybe_block)
      end
      klass
    else
      maybe_block
    end
  end
end

#_camel_keys_actionObject

Returns value set via #_camel_keys_set



316
317
318
# File 'lib/attribute_struct/attribute_struct.rb', line 316

def _camel_keys_action
  @_camel_keys_set
end

#_camel_keys_set(v) ⇒ Object

v

Symbol (:auto_disable, :auto_enable)

Sets custom rule for processed keys



311
312
313
# File 'lib/attribute_struct/attribute_struct.rb', line 311

def _camel_keys_set(v)
  @_camel_keys_set = v
end

#_dataObject

Returns underlying data hash



159
160
161
# File 'lib/attribute_struct/attribute_struct.rb', line 159

def _data
  @table
end

#_deep_copy(thing = nil) ⇒ Object

thing

Object

Returns a proper deep copy



254
255
256
257
258
259
260
261
262
263
264
265
# File 'lib/attribute_struct/attribute_struct.rb', line 254

def _deep_copy(thing=nil)
  thing ||= _dump
  if(thing.is_a?(::Enumerable))
    val = thing.map{|v| v.is_a?(::Enumerable) ? _deep_copy(v) : _do_dup(v) }
  else
    val = _do_dup(thing)
  end
  if(thing.is_a?(::Hash))
    val = __hashish[*val.flatten(1)]
  end
  val
end

#_delete(key) ⇒ Object

key

Object

Delete entry in struct with key



165
166
167
# File 'lib/attribute_struct/attribute_struct.rb', line 165

def _delete(key)
  _data.delete(_process_key(key))
end

#_do_dup(v) ⇒ Object

Returns dup of value. Converts Symbol objects to strings



244
245
246
247
248
249
250
# File 'lib/attribute_struct/attribute_struct.rb', line 244

def _do_dup(v)
  begin
    v.dup
  rescue
    v.is_a?(::Symbol) ? v.to_s : v
  end
end

#_dumpObject

Dumps the current instance to a Hash



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/attribute_struct/attribute_struct.rb', line 170

def _dump
  processed = @table.map do |key, value|
    if(value.is_a?(::Enumerable))
      flat = value.map do |v|
        v.is_a?(_klass) ? v._dump : v
      end
      val = value.is_a?(::Hash) ? __hashish[*flat.flatten(1)] : flat
    elsif(value.is_a?(_klass))
      val = value._dump
    else
      val = value
    end
    [key, val]
  end
  __hashish[*processed.flatten(1)]
end

#_keysObject

Returns current keys within struct



154
155
156
# File 'lib/attribute_struct/attribute_struct.rb', line 154

def _keys
  _data.keys
end

#_klassObject Also known as: class

Helper to return class of current instance



293
294
295
# File 'lib/attribute_struct/attribute_struct.rb', line 293

def _klass
  ::AttributeStruct
end

#_klass_newObject

Helper to return new instance of current instance type



299
300
301
302
303
304
305
306
307
# File 'lib/attribute_struct/attribute_struct.rb', line 299

def _klass_new
  n = _klass.new
  unless(_camel_keys_action == :auto_discovery)
    n._camel_keys_set(_camel_keys_action)
  end
  n._camel_keys = _camel_keys
  n._parent(self)
  n
end

#_load(hashish) ⇒ Object

hashish

Hash type object

Clears current instance data and replaces with provided hash



189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/attribute_struct/attribute_struct.rb', line 189

def _load(hashish)
  @table.clear
  if(_root._camel_keys_action == :auto_discovery)
    starts = hashish.keys.map{|k|k[0,1]}
    unless(starts.detect{|k| k =~ /[A-Z]/})
      _camel_keys_set(:auto_disable)
    else
      _camel_keys_set(:auto_enable) unless _parent.nil?
    end
  end
  hashish.each do |key, value|
    key = key.dup
    if(value.is_a?(::Enumerable))
      flat = value.map do |v|
        v.is_a?(::Hash) ? _klass.new(v) : v
      end
      value = value.is_a?(::Hash) ? __hashish[*flat.flatten(1)] : flat
    end
    if(value.is_a?(::Hash))
      self._set(key)._load(value)
    else
      self._set(key, value)
    end
  end
  self
end

#_merge(target) ⇒ Object

target

AttributeStruct

Performs a deep merge and returns the resulting AttributeStruct



218
219
220
221
222
223
224
225
226
227
# File 'lib/attribute_struct/attribute_struct.rb', line 218

def _merge(target)
  source = _deep_copy
  dest = target._deep_copy
  if(defined?(::Chef))
    result = ::Chef::Mixin::DeepMerge.merge(source, dest)
  else
    result = source.deep_merge(dest)
  end
  _klass.new(result)
end

#_merge!(target) ⇒ Object

target

AttributeStruct

Performs a deep merge and updates the current instance with the resulting value



232
233
234
235
236
# File 'lib/attribute_struct/attribute_struct.rb', line 232

def _merge!(target)
  result = _merge(target)._dump
  _load(result)
  self
end

#_parent(obj = nil) ⇒ Object



320
321
322
323
# File 'lib/attribute_struct/attribute_struct.rb', line 320

def _parent(obj=nil)
  @_parent = obj if obj
  @_parent
end

#_process_key(key, *args) ⇒ Object

key

String or Symbol

Processes the key and returns value based on current settings



269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
# File 'lib/attribute_struct/attribute_struct.rb', line 269

def _process_key(key, *args)
  key = key.to_s
  if(_camel_keys && _camel_keys_action)
    case _camel_keys_action
    when :auto_disable
      key._no_hump
    when :auto_enable
      key._hump
    end
  end
  if((_camel_keys && key._camel?) || args.include?(:force))
    key.to_s.split('_').map do |part|
      "#{part[0,1].upcase}#{part[1,part.size]}"
    end.join.to_sym
  else
    if(_camel_keys)
      # Convert so Hash doesn't make a new one and lose the meta
      key = ::CamelString.new(key) unless key.is_a?(::CamelString)
    end
    key
  end
end

#_rootObject



325
326
327
328
329
330
331
# File 'lib/attribute_struct/attribute_struct.rb', line 325

def _root
  r = self
  until(r._parent.nil?)
    r = r._parent
  end
  r
end

#_set(key, val = nil, &block) ⇒ Object

key

Object

val

Object

Directly set val into struct. Useful when key is not valid syntax for a ruby method



80
81
82
83
84
85
86
# File 'lib/attribute_struct/attribute_struct.rb', line 80

def _set(key, val=nil, &block)
  if(val)
    self.method_missing(key, val, &block)
  else
    self.method_missing(key, &block)
  end
end

#is_a?(klass) ⇒ Boolean Also known as: kind_of?

klass

Class

Returns if this struct is a klass

Returns:

  • (Boolean)


148
149
150
# File 'lib/attribute_struct/attribute_struct.rb', line 148

def is_a?(klass)
  klass.ancestors.include?(_klass)
end

#nil?Boolean

Returns if this struct is considered nil (empty data)

Returns:

  • (Boolean)


142
143
144
# File 'lib/attribute_struct/attribute_struct.rb', line 142

def nil?
  _data.empty?
end