Module: Ace::Support::Config::Atoms::DeepMerger
- Defined in:
- lib/ace/support/config/atoms/deep_merger.rb
Overview
Pure deep merge functions for hashes
Class Method Summary collapse
-
.coerce_to_array(value) ⇒ Array?
Coerce value to array if not nil.
-
.merge(base, other, options = {}) ⇒ Hash
Deep merge two hashes.
-
.merge_all(*hashes, **options) ⇒ Hash
Deep merge multiple hashes in order.
-
.merge_arrays(base_array, other_array, strategy) ⇒ Array
Merge two arrays based on strategy.
-
.merge_with_coercion(base_value, other_value) ⇒ Object
Merge values with scalar-to-array coercion for :coerce_union strategy.
-
.mergeable?(value) ⇒ Boolean
Check if value is mergeable.
-
.normalize_array(arr) ⇒ Array
Normalize array: remove nil/empty, deduplicate.
Class Method Details
.coerce_to_array(value) ⇒ Array?
Coerce value to array if not nil
111 112 113 114 |
# File 'lib/ace/support/config/atoms/deep_merger.rb', line 111 def coerce_to_array(value) return nil if value.nil? value.is_a?(Array) ? value : [value] end |
.merge(base, other, options = {}) ⇒ Hash
Uses shallow dup at top level (standard Ruby pattern). Nested hashes are recursively merged into new objects, so mutation risk is minimal. For a completely isolated deep copy, use: ‘merge({}, original_hash)`
Deep merge two hashes
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/ace/support/config/atoms/deep_merger.rb', line 26 def merge(base, other, = {}) return other.dup if base.nil? return base.dup if other.nil? array_strategy = [:array_strategy] || :replace result = base.dup other.each do |key, other_value| base_value = result[key] result[key] = if base_value.is_a?(Hash) && other_value.is_a?(Hash) merge(base_value, other_value, ) elsif array_strategy == :coerce_union merge_with_coercion(base_value, other_value) elsif base_value.is_a?(Array) && other_value.is_a?(Array) merge_arrays(base_value, other_value, array_strategy) else other_value end end result end |
.merge_all(*hashes, **options) ⇒ Hash
Deep merge multiple hashes in order
55 56 57 58 59 60 61 62 |
# File 'lib/ace/support/config/atoms/deep_merger.rb', line 55 def merge_all(*hashes, **) hashes = hashes.flatten.compact return {} if hashes.empty? hashes.reduce({}) do |result, hash| merge(result, hash, ) end end |
.merge_arrays(base_array, other_array, strategy) ⇒ Array
Merge two arrays based on strategy
76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/ace/support/config/atoms/deep_merger.rb', line 76 def merge_arrays(base_array, other_array, strategy) case strategy when :concat base_array + other_array when :union base_array | other_array when :replace other_array else raise MergeStrategyError, "Unknown array merge strategy: #{strategy}" end end |
.merge_with_coercion(base_value, other_value) ⇒ Object
Merge values with scalar-to-array coercion for :coerce_union strategy
93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/ace/support/config/atoms/deep_merger.rb', line 93 def merge_with_coercion(base_value, other_value) base_arr = coerce_to_array(base_value) other_arr = coerce_to_array(other_value) # New key with scalar: keep as scalar return other_value if base_arr.nil? && !other_value.is_a?(Array) # New key with array: normalize return normalize_array(other_arr) if base_arr.nil? # Existing key, new value nil: keep existing normalized return normalize_array(base_arr) if other_arr.nil? # Both have values: union and normalize normalize_array(base_arr | other_arr) end |
.mergeable?(value) ⇒ Boolean
Check if value is mergeable
67 68 69 |
# File 'lib/ace/support/config/atoms/deep_merger.rb', line 67 def mergeable?(value) value.is_a?(Hash) || value.is_a?(Array) end |
.normalize_array(arr) ⇒ Array
Normalize array: remove nil/empty, deduplicate
119 120 121 |
# File 'lib/ace/support/config/atoms/deep_merger.rb', line 119 def normalize_array(arr) arr.reject { |v| v.nil? || (v.respond_to?(:empty?) && v.empty?) }.uniq end |