Module: Chef::Node::CommonAPI

Included in:
ImmutableMash, VividMash
Defined in:
lib/chef/node/common_api.rb

Overview

shared API between VividMash and ImmutableMash, writer code can be 'shared' to keep it logically in this file by adding them to the block list in ImmutableMash.

Instance Method Summary collapse

Instance Method Details

#exist?(*path) ⇒ Boolean

return true or false based on if the attribute exists


71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/chef/node/common_api.rb', line 71

def exist?(*path)
  path.inject(self) do |memo, key|
    return false unless valid_container?(memo, key)
    if memo.is_a?(Hash)
      if memo.key?(key)
        memo[key]
      else
        return false
      end
    elsif memo.is_a?(Array)
      if memo.length > key
        memo[key]
      else
        return false
      end
    end
  end
  true
end

#read(*path) ⇒ Object

this is a safe non-autovivifying reader that returns nil if the attribute does not exist


92
93
94
95
96
# File 'lib/chef/node/common_api.rb', line 92

def read(*path)
  read!(*path)
rescue Chef::Exceptions::NoSuchAttribute
  nil
end

#read!(*path) ⇒ Object

non-autovivifying reader that throws an exception if the attribute does not exist


99
100
101
102
103
104
# File 'lib/chef/node/common_api.rb', line 99

def read!(*path)
  raise Chef::Exceptions::NoSuchAttribute unless exist?(*path)
  path.inject(self) do |memo, key|
    memo[key]
  end
end

FIXME:(?) does anyone really like the autovivifying reader that we have and wants the same behavior? readers that write? ugh...


108
109
110
111
112
# File 'lib/chef/node/common_api.rb', line 108

def unlink(*path, last)
  hash = path.empty? ? self : read(*path)
  return nil unless hash.is_a?(Hash) || hash.is_a?(Array)
  hash.delete(last)
end

#unlink!(*path) ⇒ Object


114
115
116
117
# File 'lib/chef/node/common_api.rb', line 114

def unlink!(*path)
  raise Chef::Exceptions::NoSuchAttribute unless exist?(*path)
  unlink(*path)
end

#write(*args, &block) ⇒ Object

  • autovivifying / autoreplacing writer
  • non-container-ey intermediate objects are replaced with hashes

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/chef/node/common_api.rb', line 34

def write(*args, &block)
  value = block_given? ? yield : args.pop
  last = args.pop
  prev_memo = prev_key = nil
  chain = args.inject(self) do |memo, key|
    if !valid_container?(memo, key)
      prev_memo[prev_key] = {}
      memo = prev_memo[prev_key]
    end
    prev_memo = memo
    prev_key = key
    memo[key]
  end
  if !valid_container?(chain, last)
    prev_memo[prev_key] = {}
    chain = prev_memo[prev_key]
  end
  chain[last] = value
end

#write!(*args, &block) ⇒ Object

this autovivifies, but can throw NoSuchAttribute when trying to access #[] on something that is not a container ("schema violation" issues).


57
58
59
60
61
62
63
64
65
66
# File 'lib/chef/node/common_api.rb', line 57

def write!(*args, &block)
  value = block_given? ? yield : args.pop
  last = args.pop
  obj = args.inject(self) do |memo, key|
    raise Chef::Exceptions::AttributeTypeMismatch unless valid_container?(memo, key)
    memo[key]
  end
  raise Chef::Exceptions::AttributeTypeMismatch unless valid_container?(obj, last)
  obj[last] = value
end