Module: Liminal::Internal::SchemaMerge
- Defined in:
- lib/liminal/internal/schema_merge.rb
Overview
Deterministic schema-aware merge operations.
Class Method Summary collapse
-
.combine(left, right) ⇒ Object
Combine two conjunctive schema fragments without weakening either one.
- .deep_copy(value) ⇒ Object
- .ordered_union(left, right) ⇒ Object
-
.override(generated, supplied) ⇒ Object
Apply an enrichment override.
Class Method Details
.combine(left, right) ⇒ Object
Combine two conjunctive schema fragments without weakening either one.
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/liminal/internal/schema_merge.rb', line 10 def combine(left, right) left = deep_copy(left) right = deep_copy(right) return right if left.empty? return left if right.empty? return left if left == right merged = left.dup right.each do |key, right_value| unless merged.key?(key) merged[key] = right_value next end left_value = merged[key] merged_value = combine_value(key, left_value, right_value) return all_of(left, right) if merged_value.equal?(CONFLICT) merged[key] = merged_value end merged end |
.deep_copy(value) ⇒ Object
55 56 57 58 59 60 61 62 63 64 |
# File 'lib/liminal/internal/schema_merge.rb', line 55 def deep_copy(value) case value when Hash value.each_with_object({}) { |(key, item), copy| copy[key] = deep_copy(item) } when Array value.map { |item| deep_copy(item) } else value end end |
.ordered_union(left, right) ⇒ Object
66 67 68 69 70 |
# File 'lib/liminal/internal/schema_merge.rb', line 66 def ordered_union(left, right) (left + right).each_with_object([]) do |value, values| values << value unless values.include?(value) end end |
.override(generated, supplied) ⇒ Object
Apply an enrichment override. Override values win except that required arrays are unioned and nested hashes are recursively merged.
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/liminal/internal/schema_merge.rb', line 37 def override(generated, supplied) result = generated.each_with_object({}) do |(key, value), copy| copy[key] = deep_copy(value) end supplied.each do |key, value| result[key] = if key == "required" && result[key].is_a?(Array) && value.is_a?(Array) ordered_union(result[key], value) elsif result[key].is_a?(Hash) && value.is_a?(Hash) override(result[key], value) else deep_copy(value) end end result end |