Class: Chef::Node::VividMash

Inherits:
Mash show all
Defined in:
lib/chef/node/attribute_collections.rb

Overview

VividMash

VividMash is identical to a Mash, with a few exceptions:

  • It has a reference to the root Chef::Node::Attribute to which it belongs, and will trigger cache invalidation on that object when mutated.

  • It auto-vivifies, that is a reference to a missing element will result in the creation of a new VividMash for that key. (This only works when using the element reference method, ‘[]` – other methods, such as #fetch, work as normal).

  • It supports a set_unless flag (via the root Attribute object) which allows ‘||=` style behavior (`||=` does not work with auto-vivification). This is only implemented for #[]=; methods such as #store work as normal.

  • attr_accessor style element set and get are supported via method_missing

Constant Summary collapse

MUTATOR_METHODS =

Methods that mutate a VividMash. Each of them is overridden so that it also invalidates the cached merged_attributes on the root Attribute object.

[
  :clear,
  :delete,
  :delete_if,
  :keep_if,
  :merge!,
  :update,
  :reject!,
  :replace,
  :select!,
  :shift
]

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Mash

#default, #delete, #except, #fetch, from_hash, #initialize_copy, #key?, #merge, #regular_update, #regular_writer, #stringify_keys!, #symbolize_keys, #to_hash, #update, #values_at

Constructor Details

#initialize(root, data = {}) ⇒ VividMash

Returns a new instance of VividMash.



137
138
139
140
# File 'lib/chef/node/attribute_collections.rb', line 137

def initialize(root, data={})
  @root = root
  super(data)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(symbol, *args) ⇒ Object



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/chef/node/attribute_collections.rb', line 165

def method_missing(symbol, *args)
  # Calling `puts arg` implicitly calls #to_ary on `arg`. If `arg` does
  # not implement #to_ary, ruby recognizes it as a single argument, and
  # if it returns an Array, then ruby prints each element. If we don't
  # account for that here, we'll auto-vivify a VividMash for the key
  # :to_ary which creates an unwanted key and raises a TypeError.
  if symbol == :to_ary
    super
  elsif args.empty?
    self[symbol]
  elsif symbol.to_s =~ /=$/
    key_to_set = symbol.to_s[/^(.+)=$/, 1]
    self[key_to_set] = (args.length == 1 ? args[0] : args)
  else
    raise NoMethodError, "Undefined node attribute or method `#{symbol}' on `node'. To set an attribute, use `#{symbol}=value' instead."
  end
end

Instance Attribute Details

#rootObject (readonly)

Returns the value of attribute root.



107
108
109
# File 'lib/chef/node/attribute_collections.rb', line 107

def root
  @root
end

Instance Method Details

#[](key) ⇒ Object



142
143
144
145
146
147
148
149
150
151
# File 'lib/chef/node/attribute_collections.rb', line 142

def [](key)
  root.top_level_breadcrumb ||= key
  value = super
  if !key?(key)
    value = self.class.new(root)
    self[key] = value
  else
    value
  end
end

#[]=(key, value) ⇒ Object



153
154
155
156
157
158
159
160
161
# File 'lib/chef/node/attribute_collections.rb', line 153

def []=(key, value)
  root.top_level_breadcrumb ||= key
  if set_unless? && key?(key)
    self[key]
  else
    root.reset_cache(root.top_level_breadcrumb)
    super
  end
end

#convert_key(key) ⇒ Object



187
188
189
# File 'lib/chef/node/attribute_collections.rb', line 187

def convert_key(key)
  super
end

#convert_value(value) ⇒ Object

Mash uses #convert_value to mashify values on input. We override it here to convert hash or array values to VividMash or AttrArray for consistency and to ensure that the added parts of the attribute tree will have the correct cache invalidation behavior.



195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/chef/node/attribute_collections.rb', line 195

def convert_value(value)
  case value
  when VividMash
    value
  when Hash
    VividMash.new(root, value)
  when Array
    AttrArray.new(root, value)
  else
    value
  end
end

#dupObject



208
209
210
# File 'lib/chef/node/attribute_collections.rb', line 208

def dup
  Mash.new(self)
end

#set_unless?Boolean

Returns:

  • (Boolean)


183
184
185
# File 'lib/chef/node/attribute_collections.rb', line 183

def set_unless?
  @root.set_unless?
end