Class: Ace::Assign::Molecules::StepRenumberer

Inherits:
Object
  • Object
show all
Defined in:
lib/ace/assign/molecules/step_renumberer.rb

Overview

Handles step file renumbering with cascade support and atomic operations.

Extracted from AssignmentExecutor to provide:

  • Testable renumbering logic

  • Transactional rename with rollback on failure

  • Parent metadata updates for descendants

Examples:

Basic usage

renumberer = StepRenumberer.new(step_writer: step_writer, queue_scanner: scanner)
renumberer.renumber(steps_dir, ["010", "011"])

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(step_writer:, queue_scanner:) ⇒ StepRenumberer

Returns a new instance of StepRenumberer.



21
22
23
24
# File 'lib/ace/assign/molecules/step_renumberer.rb', line 21

def initialize(step_writer:, queue_scanner:)
  @step_writer = step_writer
  @queue_scanner = queue_scanner
end

Instance Attribute Details

#queue_scannerObject (readonly)

Returns the value of attribute queue_scanner.



19
20
21
# File 'lib/ace/assign/molecules/step_renumberer.rb', line 19

def queue_scanner
  @queue_scanner
end

#step_writerObject (readonly)

Returns the value of attribute step_writer.



19
20
21
# File 'lib/ace/assign/molecules/step_renumberer.rb', line 19

def step_writer
  @step_writer
end

Instance Method Details

#renumber(steps_dir, numbers_to_shift) ⇒ Hash

Renumber steps by shifting their file numbers. Also cascades to all descendants to prevent orphaning children.

Parameters:

  • steps_dir (String)

    Path to steps directory

  • numbers_to_shift (Array<String>)

    Step numbers to shift

Returns:

  • (Hash)

    Result with :renamed (count) and :rollback_needed (bool)



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/ace/assign/molecules/step_renumberer.rb', line 32

def renumber(steps_dir, numbers_to_shift)
  return {renamed: 0, rollback_needed: false} if numbers_to_shift.empty?

  all_numbers = queue_scanner.step_numbers(steps_dir)
  sorted_steps = build_shift_list(numbers_to_shift, all_numbers)

  # Track operations for potential rollback
  completed_renames = []
  rollback_needed = false

  begin
    sorted_steps.each do |old_number|
      new_number = calculate_new_number(old_number, numbers_to_shift)
      next if new_number == old_number

      # Calculate new parent for frontmatter update
      new_parent = calculate_new_parent(old_number, numbers_to_shift)

      rename_result = rename_step_files(
        steps_dir,
        old_number,
        new_number,
        new_parent: new_parent
      )

      completed_renames << {old: old_number, new: new_number, files: rename_result[:files]}
    end
  rescue => e
    rollback_needed = true
    rollback_renames(completed_renames)
    raise e
  end

  {renamed: completed_renames.size, rollback_needed: rollback_needed}
end