Class: Puppet::Pops::DeepMergeStrategy

Inherits:
MergeStrategy show all
Defined in:
lib/puppet/pops/merge_strategy.rb

Overview

Documentation copied from github.com/danielsdeleo/deep_merge/blob/master/lib/deep_merge/core.rb altered with respect to preserve_unmergeables since this implementation always disables that option.

The destination is dup’ed before the deep_merge is called to allow frozen objects as values.

deep_merge method permits merging of arbitrary child elements. The two top level elements must be hashes. These hashes can contain unlimited (to stack limit) levels of child elements. These child elements to not have to be of the same types. Where child elements are of the same type, deep_merge will attempt to merge them together. Where child elements are not of the same type, deep_merge will skip or optionally overwrite the destination element with the contents of the source element at that level. So if you have two hashes like this:

source = {:x => [1,2,3], :y => 2}
dest =   {:x => [4,5,'6'], :y => [7,8,9]}
dest.deep_merge!(source)
Results: {:x => [1,2,3,4,5,'6'], :y => 2}

“deep_merge” will unconditionally overwrite any unmergeables and merge everything else.

Options:

Options are specified in the last parameter passed, which should be in hash format:
hash.deep_merge!({:x => [1,2]}, {:knockout_prefix => '--'})
- 'knockout_prefix' Set to string value to signify prefix which deletes elements from existing element. Defaults is _undef_
- 'sort_merged_arrays' Set to _true_ to sort all arrays that are merged together. Default is _false_
- 'merge_hash_arrays' Set to _true_ to merge hashes within arrays. Default is _false_

Selected Options Details: :knockout_prefix => The purpose of this is to provide a way to remove elements

from existing Hash by specifying them in a special way in incoming hash
 source = {:x => ['--1', '2']}
 dest   = {:x => ['1', '3']}
 dest.ko_deep_merge!(source)
 Results: {:x => ['2','3']}
Additionally, if the knockout_prefix is passed alone as a string, it will cause
the entire element to be removed:
 source = {:x => '--'}
 dest   = {:x => [1,2,3]}
 dest.ko_deep_merge!(source)
 Results: {:x => ""}

:merge_hash_arrays => merge hashes within arrays

source = {:x => [{:y => 1}]}
dest   = {:x => [{:z => 2}]}
dest.deep_merge!(source, {:merge_hash_arrays => true})
Results: {:x => [{:y => 1, :z => 2}]}

Direct Known Subclasses

UnconstrainedDeepMergeStrategy

Constant Summary collapse

INSTANCE =
new(EMPTY_HASH)

Constants inherited from MergeStrategy

MergeStrategy::NOT_FOUND

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from MergeStrategy

add_strategy, #configuration, #convert_value, #initialize, #lookup, merge, #merge, #merge_lookup, #merge_single, #options, strategy, strategy_keys

Constructor Details

This class inherits a constructor from Puppet::Pops::MergeStrategy

Class Method Details

.keyObject



368
369
370
# File 'lib/puppet/pops/merge_strategy.rb', line 368

def self.key
  :deep
end

.options_tTypes::PAnyType

Returns a type that allows all deep_merge options except ‘preserve_unmergeables’ since we force the setting of that option to false

Returns:

  • (Types::PAnyType)

    the puppet type used when validating the options hash



399
400
401
402
403
404
405
406
407
# File 'lib/puppet/pops/merge_strategy.rb', line 399

def options_t
  @options_t ||= Types::TypeParser.singleton.parse('Struct[{'\
                                                   "strategy=>Optional[Pattern[#{key}]],"\
                                                   'knockout_prefix=>Optional[String],'\
                                                   'merge_debug=>Optional[Boolean],'\
                                                   'merge_hash_arrays=>Optional[Boolean],'\
                                                   'sort_merged_arrays=>Optional[Boolean],'\
                                                   '}]')
end

Instance Method Details

#checked_merge(e1, e2) ⇒ Object



372
373
374
375
376
377
# File 'lib/puppet/pops/merge_strategy.rb', line 372

def checked_merge(e1, e2)
  dm_options = { :preserve_unmergeables => false }
  options.each_pair { |k, v| dm_options[k.to_sym] = v unless k == 'strategy' }
  # e2 (the destination) is deep cloned to avoid that the passed in object mutates
  DeepMerge.deep_merge!(e1, deep_clone(e2), dm_options)
end

#deep_clone(value) ⇒ Object



379
380
381
382
383
384
385
386
387
388
389
390
# File 'lib/puppet/pops/merge_strategy.rb', line 379

def deep_clone(value)
  case value
  when Hash
    result = value.clone
    value.each { |k, v| result[k] = deep_clone(v) }
    result
  when Array
    value.map { |v| deep_clone(v) }
  else
    value
  end
end