Class: Ecoportal::API::GraphQL::Diff::CommandSynthesizer
- Inherits:
-
Object
- Object
- Ecoportal::API::GraphQL::Diff::CommandSynthesizer
- Defined in:
- lib/ecoportal/api/graphql/diff/command_synthesizer.rb
Overview
Turns a set of Diff::Change objects (from VersionDiff) into an ordered batch of built
WorkflowCommand hashes — the replayable "commit".
changes = VersionDiff.new(v1, v2).changes synth = CommandSynthesizer.new(changes) synth.commands # => [{ editFieldConfiguration: ... }, { removeField: ... }, ...] synth.unsupported # => Change, ...
SCOPE — self-version diff by default. The ids carried by each Change are REAL server ids of the SAME object across two of its own versions, so they can be replayed as-is. For a cross-object diff (UAT<->PROD, page<->template) every id in the emitted commands must first be translated through a pairing map before replay.
RESOLVER — some edits address a TARGET node by an id the Change does not carry (a field
move needs the destination section id; a section move needs the destination stage id).
VersionDiff records those targets by their human key (section heading, stage name) because
that is all a structural diff knows. Pass a resolver that maps
resolve(kind, key) => id (e.g. the pairing engine's ledger, or a lookup built from the
target doc) and those moves become supported. WITHOUT a resolver they stay UNSUPPORTED —
the synthesiser never guesses a target id.
ORDERING — structure before children, and within a kind: removes, then adds, then moves, then edits. Structural creates (stages, sections, fields) precede the option-level edits that depend on them, so a straight left-to-right replay stays valid.
SAFETY — a change with no faithful command is NEVER guessed. It is collected into
unsupported for the caller to inspect. In particular a field type change has no edit
command in the schema (there is no editFieldType), so it is reported as unsupported rather
than silently rebuilt (a rebuild would drop the field's data and history).
Constant Summary collapse
- KIND_ORDER =
Emit order: structure first (stages -> sections -> fields), then options; and within a kind, removes -> adds -> moves -> edits, so a straight left-to-right replay stays valid.
{ stage: 0, section: 1, field: 2, field_config: 3, gauge_stop: 4, option: 5 }.freeze
- OP_ORDER =
{ removed: 0, added: 1, moved: 2, changed: 3 }.freeze
Instance Method Summary collapse
-
#commands ⇒ Object
Ordered Array of built command hashes (each
{ commandKey => {..input..} }). -
#initialize(changes, resolver: nil, thread_placeholders: false) ⇒ CommandSynthesizer
constructor
A new instance of CommandSynthesizer.
-
#unsupported ⇒ Object
Changes that could not be mapped to a command.
Constructor Details
#initialize(changes, resolver: nil, thread_placeholders: false) ⇒ CommandSynthesizer
Returns a new instance of CommandSynthesizer.
49 50 51 52 53 54 |
# File 'lib/ecoportal/api/graphql/diff/command_synthesizer.rb', line 49 def initialize(changes, resolver: nil, thread_placeholders: false) @changes = Array(changes) @resolver = resolver @thread_placeholders = thread_placeholders @unsupported = [] end |
Instance Method Details
#commands ⇒ Object
Ordered Array of built command hashes (each { commandKey => {..input..} }).
57 58 59 |
# File 'lib/ecoportal/api/graphql/diff/command_synthesizer.rb', line 57 def commands @commands ||= build_all end |
#unsupported ⇒ Object
Changes that could not be mapped to a command. Populated as a side effect of commands.
62 63 64 65 |
# File 'lib/ecoportal/api/graphql/diff/command_synthesizer.rb', line 62 def unsupported commands @unsupported end |