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)


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

def exist?(*path)
  root.top_level_breadcrumb = nil if respond_to?(:root)
  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



95
96
97
98
99
100
101
# File 'lib/chef/node/common_api.rb', line 95

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



104
105
106
107
108
109
110
# File 'lib/chef/node/common_api.rb', line 104

def read!(*path)
  raise Chef::Exceptions::NoSuchAttribute unless exist?(*path)
  root.top_level_breadcrumb = nil if respond_to?(:root)
  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…



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

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

#unlink!(*path) ⇒ Object



122
123
124
125
# File 'lib/chef/node/common_api.rb', line 122

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
53
# File 'lib/chef/node/common_api.rb', line 34

def write(*args, &block)
  root.top_level_breadcrumb = nil if respond_to?(:root)
  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).



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

def write!(*args, &block)
  root.top_level_breadcrumb = nil if respond_to?(:root)
  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