Class: Psych::Merge::PartialTemplateMerger

Inherits:
Object
  • Object
show all
Defined in:
lib/psych/merge/partial_template_merger.rb

Overview

Merges a partial YAML template into a specific key path of a destination document.

Unlike the full SmartMerger which merges entire documents, PartialTemplateMerger:

  1. Finds a specific key path in the destination (e.g., [“AllCops”, “Exclude”])
  2. Merges template content at that location
  3. Leaves the rest of the destination unchanged

Examples:

Basic usage - merge into existing key

template = <<~YAML
  - examples/**/*
  - vendor/**/*
YAML

destination = <<~YAML
  AllCops:
    Exclude:
      - tmp/**/*
    TargetRubyVersion: 3.2
YAML

merger = PartialTemplateMerger.new(
  template: template,
  destination: destination,
  key_path: ["AllCops", "Exclude"]
)
result = merger.merge

Adding a new nested key

merger = PartialTemplateMerger.new(
  template: "enable",
  destination: "AllCops:\n  Exclude: []",
  key_path: ["AllCops", "NewCops"],
  when_missing: :add
)

Defined Under Namespace

Classes: Result

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(template:, destination:, key_path:, preference: :destination, add_missing: true, remove_missing: false, when_missing: :skip, recursive: true) ⇒ PartialTemplateMerger

Initialize a PartialTemplateMerger.

Parameters:

  • template (String)

    The template content to merge

  • destination (String)

    The destination content

  • key_path (Array<String, Integer>)

    Path to target key (e.g., [“AllCops”, “Exclude”])

  • preference (Symbol) (defaults to: :destination)

    Which content wins on conflicts (:template or :destination)

  • add_missing (Boolean) (defaults to: true)

    Whether to add template items not in destination

  • remove_missing (Boolean) (defaults to: false)

    Whether to remove destination items not in template

  • when_missing (Symbol) (defaults to: :skip)

    Behavior when key path not found (:skip, :add)

  • recursive (Boolean) (defaults to: true)

    Whether to recursively merge nested structures



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/psych/merge/partial_template_merger.rb', line 92

def initialize(
  template:,
  destination:,
  key_path:,
  preference: :destination,
  add_missing: true,
  remove_missing: false,
  when_missing: :skip,
  recursive: true
)
  @template = template
  @destination = destination
  @key_path = Array(key_path)
  @preference = preference
  @add_missing = add_missing
  @remove_missing = remove_missing
  @when_missing = when_missing
  @recursive = recursive

  validate_key_path!
end

Instance Attribute Details

#add_missingBoolean (readonly)

Returns Whether to add template items not in destination.

Returns:

  • (Boolean)

    Whether to add template items not in destination



71
72
73
# File 'lib/psych/merge/partial_template_merger.rb', line 71

def add_missing
  @add_missing
end

#destinationString (readonly)

Returns The destination content.

Returns:

  • (String)

    The destination content



62
63
64
# File 'lib/psych/merge/partial_template_merger.rb', line 62

def destination
  @destination
end

#key_pathArray<String, Integer> (readonly)

Returns Path to the target key (e.g., [“AllCops”, “Exclude”]).

Returns:

  • (Array<String, Integer>)

    Path to the target key (e.g., [“AllCops”, “Exclude”])



65
66
67
# File 'lib/psych/merge/partial_template_merger.rb', line 65

def key_path
  @key_path
end

#preferenceSymbol (readonly)

Returns Merge preference (:template or :destination).

Returns:

  • (Symbol)

    Merge preference (:template or :destination)



68
69
70
# File 'lib/psych/merge/partial_template_merger.rb', line 68

def preference
  @preference
end

#recursiveBoolean (readonly)

Returns Whether to recursively merge nested structures.

Returns:

  • (Boolean)

    Whether to recursively merge nested structures



80
81
82
# File 'lib/psych/merge/partial_template_merger.rb', line 80

def recursive
  @recursive
end

#remove_missingBoolean (readonly)

Returns Whether to remove destination items not in template.

Returns:

  • (Boolean)

    Whether to remove destination items not in template



74
75
76
# File 'lib/psych/merge/partial_template_merger.rb', line 74

def remove_missing
  @remove_missing
end

#templateString (readonly)

Returns The template content to merge.

Returns:

  • (String)

    The template content to merge



59
60
61
# File 'lib/psych/merge/partial_template_merger.rb', line 59

def template
  @template
end

#when_missingSymbol (readonly)

Returns What to do when key path not found (:skip, :add).

Returns:

  • (Symbol)

    What to do when key path not found (:skip, :add)



77
78
79
# File 'lib/psych/merge/partial_template_merger.rb', line 77

def when_missing
  @when_missing
end

Instance Method Details

#mergeResult

Perform the partial template merge.

Returns:

  • (Result)

    The merge result



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/psych/merge/partial_template_merger.rb', line 117

def merge
  d_analysis = FileAnalysis.new(destination)

  unless d_analysis.valid?
    return Result.new(
      content: destination,
      has_key_path: false,
      changed: false,
      message: "Failed to parse destination: #{d_analysis.errors.join(", ")}",
    )
  end

  # Navigate to the key path
  target_entry = find_key_path(d_analysis)

  if target_entry.nil?
    return handle_missing_key_path(d_analysis)
  end

  # Perform the merge at the found location
  perform_merge_at_path(d_analysis, target_entry)
end