Class: Chef::Node::MultiMash
- Inherits:
-
Object
- Object
- Chef::Node::MultiMash
- Defined in:
- lib/chef/node/attribute_collections.rb
Overview
MultiMash
This is a Hash-like object that contains multiple VividMashes in it. Its purpose is so that the user can descend into the mash and delete a subtree from all of the Mash objects (used to delete all values in a subtree from default, force_default, role_default and env_default at the same time). The assignment operator strictly does assignment (does no merging) and works by deleting the subtree and then assigning to the last mash which passed in the initializer.
A lot of the complexity of this class comes from the fact that at any key value some or all of the mashes may walk off their ends and become nil or true or something. The schema may change so that one precidence leve may be ‘true’ object and another may be a VividMash. It is also possible that one or many of them may transition from VividMashes to Hashes or Arrays.
It also supports the case where you may be deleting a key using node.rm in which case if intermediate keys all walk off into nil then you don’t want to be autovivifying keys as you go. On the other hand you may be using node.force_default! in which case you’ll wind up with a []= operator at the end and you want autovivification, so we conditionally have to support either operation.
@todo: can we have an autovivify class that decorates a class that doesn’t autovivify or something so that the code is less awful?
Instance Attribute Summary collapse
-
#mashes ⇒ Object
readonly
Returns the value of attribute mashes.
-
#opts ⇒ Object
readonly
Returns the value of attribute opts.
-
#primary_mash ⇒ Object
readonly
Returns the value of attribute primary_mash.
-
#root ⇒ Object
readonly
Returns the value of attribute root.
Instance Method Summary collapse
- #[](key) ⇒ Object
- #[]=(key, value) ⇒ Object
- #delete(key) ⇒ Object
-
#element(key = nil, *subkeys) ⇒ Object
mash.element(‘foo’, ‘bar’) is the same as mash[‘bar’].
-
#initialize(root, primary_mash, mashes, opts = {}) ⇒ MultiMash
constructor
Initialize with an array of mashes.
Constructor Details
#initialize(root, primary_mash, mashes, opts = {}) ⇒ MultiMash
Initialize with an array of mashes. For the delete return value to work properly the mashes must come from the same attribute level (i.e. all override or all default, but not a mix of both).
244 245 246 247 248 249 250 |
# File 'lib/chef/node/attribute_collections.rb', line 244 def initialize(root, primary_mash, mashes, opts = {}) @root = root @primary_mash = primary_mash @mashes = mashes @opts = opts @opts[:autovivify] = true if @opts[:autovivify].nil? end |
Instance Attribute Details
#mashes ⇒ Object (readonly)
Returns the value of attribute mashes.
237 238 239 |
# File 'lib/chef/node/attribute_collections.rb', line 237 def mashes @mashes end |
#opts ⇒ Object (readonly)
Returns the value of attribute opts.
238 239 240 |
# File 'lib/chef/node/attribute_collections.rb', line 238 def opts @opts end |
#primary_mash ⇒ Object (readonly)
Returns the value of attribute primary_mash.
239 240 241 |
# File 'lib/chef/node/attribute_collections.rb', line 239 def primary_mash @primary_mash end |
#root ⇒ Object (readonly)
Returns the value of attribute root.
236 237 238 |
# File 'lib/chef/node/attribute_collections.rb', line 236 def root @root end |
Instance Method Details
#[](key) ⇒ Object
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 |
# File 'lib/chef/node/attribute_collections.rb', line 252 def [](key) # handle the secondary mashes new_mashes = [] mashes.each do |mash| new_mash = safe_evalute_key(mash, key) # secondary mashes never autovivify so once they fall into nil, we just stop tracking them new_mashes.push(new_mash) unless new_mash.nil? end new_primary_mash = safe_evalute_key(primary_mash, key) if new_primary_mash.nil? && @opts[:autovivify] primary_mash[key] = VividMash.new(root) new_primary_mash = primary_mash[key] end MultiMash.new(root, new_primary_mash, new_mashes, opts) end |
#[]=(key, value) ⇒ Object
271 272 273 274 275 276 277 278 279 280 |
# File 'lib/chef/node/attribute_collections.rb', line 271 def []=(key, value) if primary_mash.nil? # This theoretically should never happen since node#force_default! setter methods will autovivify and # node#rm methods do not end in #[]= operators. raise TypeError, "No autovivification was specified initially on a method chain ending in assignment" end ret = delete(key) primary_mash[key] = value ret end |
#delete(key) ⇒ Object
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 |
# File 'lib/chef/node/attribute_collections.rb', line 289 def delete(key) # the return value is a deep merge which is correct semantics when # merging between attributes on the same level (this would be incorrect # if passed both override and default attributes which would need hash_only # merging). ret = mashes.inject(Mash.new) do |merged, mash| Chef::Mixin::DeepMerge.merge(merged, mash) end ret = Chef::Mixin::DeepMerge.merge(ret, primary_mash) mashes.each do |mash| mash.delete(key) if mash.respond_to?(:delete) end primary_mash.delete(key) if primary_mash.respond_to?(:delete) ret[key] end |
#element(key = nil, *subkeys) ⇒ Object
mash.element(‘foo’, ‘bar’) is the same as mash[‘bar’]
283 284 285 286 287 |
# File 'lib/chef/node/attribute_collections.rb', line 283 def element(key = nil, *subkeys) return self if key.nil? submash = self[key] subkeys.empty? ? submash : submash.element(*subkeys) end |