module Chef::Node::CommonAPI

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.

Public Instance Methods

dig(*path)
Alias for: read
exist?(*path) click to toggle source

return true or false based on if the attribute exists

# 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) click to toggle source

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

# File lib/chef/node/common_api.rb, line 95
def read(*path)
  read!(*path)
rescue Chef::Exceptions::NoSuchAttribute
  nil
end
Also aliased as: dig
read!(*path) click to toggle source

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

# 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
write(*args) { |: pop| ... } click to toggle source
  • autovivifying / autoreplacing writer

  • non-container-ey intermediate objects are replaced with hashes

# 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) { |: pop| ... } click to toggle source

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

# 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

Private Instance Methods

valid_container?(obj, key) click to toggle source

method-style access to attributes

# File lib/chef/node/common_api.rb, line 26
def valid_container?(obj, key)
  obj.is_a?(Hash) || (obj.is_a?(Array) && key.is_a?(Integer))
end