Skip to content

Commit 3ade633

Browse files
committed
Populate sprint lookup incrementally on copy
Assigns `state.sprint_id_lookup` after each created sprint (not once after the loop) so a mid-loop `create!` failure leaves the partial mapping intact instead of nil, which would otherwise make copied work packages retain the source project's sprint. Per-iteration assignment is required because `state` is a `Hashie::Mash`: assigning the empty hash before the loop converts it into a separate `Mash` instance, so later mutations of the plain `Hash` are invisible to `state`. Also strengthens the sprint-copy spec with a source/target decoupling assertion.
1 parent 380e029 commit 3ade633

2 files changed

Lines changed: 10 additions & 2 deletions

File tree

modules/backlogs/app/services/projects/copy/sprints_dependent_service.rb

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,14 @@ def copy_dependency(*)
4747
attributes = source_sprint.attributes.dup.except("id", "project_id", "created_at", "updated_at")
4848
sprint = target.sprints.create!(attributes)
4949
sprint_id_map[source_sprint.id] = sprint.id
50-
end
5150

52-
state.sprint_id_lookup = sprint_id_map
51+
# Re-assigned on every iteration (rather than once after the loop) because `state` is a
52+
# Hashie::Mash: assignment converts the Hash into a new Mash, breaking object identity, so
53+
# later mutations of `sprint_id_map` alone would not be visible through `state.sprint_id_lookup`.
54+
# Keeping the lookup current after each sprint also means a mid-loop `create!` failure (rescued
55+
# by `Copy::Dependency#perform`) leaves the partial mapping intact instead of nil.
56+
state.sprint_id_lookup = sprint_id_map
57+
end
5358
end
5459
end
5560
end

modules/backlogs/spec/services/projects/copy_service_integration_spec.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@
144144
copied_sprint = project_copy.sprints.first
145145
expect(copied_sprint.id).not_to eq(source_sprint.id)
146146
expect(copied_sprint.project).to eq(project_copy)
147+
148+
copied_sprint.update!(name: "Renamed Copy")
149+
expect(source_sprint.reload.name).to eq("Sprint A")
147150
end
148151
end
149152

0 commit comments

Comments
 (0)