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

Returns:

  • (Boolean)


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
  return 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
97
98
# File 'lib/chef/node/common_api.rb', line 92

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

#read!(*path) ⇒ Object

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



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

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…



110
111
112
113
114
# File 'lib/chef/node/common_api.rb', line 110

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



116
117
118
119
# File 'lib/chef/node/common_api.rb', line 116

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