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)
  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 Also known as: dig

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



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

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



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

def read!(*path)
  raise Chef::Exceptions::NoSuchAttribute.new(path.join ".") 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…



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

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



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

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|
    unless valid_container?(memo, key)
      prev_memo[prev_key] = {}
      memo = prev_memo[prev_key]
    end
    prev_memo = memo
    prev_key = key
    memo[key]
  end
  unless 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
67
68
# 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