models: explicitely save procedure's new revision
Deep-cloned objects have all their relationships stale. Thus, for a newly deep-cloned revision, `revision.types_de_champs` returns `[]`, even when it actually has associated types de champ. This causes consecutive champs creations and re-ordering to fail in subtle ways, like: ``` procedure.draft_revision.add_type_de_champ(…) procedure.publish_revision! procedure.draft_revision.add_type_de_champ(…) procedure.draft_revision.move_type_de_champ(…) # this will fail ``` As `publish_revision!` created a new stale revision, moving the type de champ fails because not all existing champs are found until the object is refreshed. We don't hit this path in production, because usually only a single operation is made in a request. To fix this, save the new revision before associating it as the draft procedure. (Another option would be to `reload` the revision after creation, but this seems better contained and matches the name of the method.)
This commit is contained in:
parent
73faa569e8
commit
e5f5440663
2 changed files with 47 additions and 1 deletions
|
@ -678,7 +678,9 @@ class Procedure < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_new_revision
|
def create_new_revision
|
||||||
draft_revision.deep_clone(include: [:revision_types_de_champ, :revision_types_de_champ_private])
|
draft_revision
|
||||||
|
.deep_clone(include: [:revision_types_de_champ, :revision_types_de_champ_private])
|
||||||
|
.tap(&:save!)
|
||||||
end
|
end
|
||||||
|
|
||||||
def average_dossier_weight
|
def average_dossier_weight
|
||||||
|
|
|
@ -695,6 +695,50 @@ describe Procedure do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "#publish_revision!" do
|
||||||
|
let(:procedure) { create(:procedure, :published) }
|
||||||
|
let(:tdc_attributes) { { type_champ: :number, libelle: 'libelle 1' } }
|
||||||
|
let(:publication_date) { Time.zone.local(2021, 1, 1, 12, 00, 00) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
procedure.draft_revision.add_type_de_champ(tdc_attributes)
|
||||||
|
end
|
||||||
|
|
||||||
|
subject do
|
||||||
|
Timecop.freeze(publication_date) do
|
||||||
|
procedure.publish_revision!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'publishes the new revision' do
|
||||||
|
subject
|
||||||
|
expect(procedure.published_revision).to be_present
|
||||||
|
expect(procedure.published_revision.published_at).to eq(publication_date)
|
||||||
|
expect(procedure.published_revision.types_de_champ.first.libelle).to eq('libelle 1')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'creates a new draft revision' do
|
||||||
|
expect { subject }.to change(ProcedureRevision, :count).by(1)
|
||||||
|
expect(procedure.draft_revision).to be_present
|
||||||
|
expect(procedure.draft_revision.revision_types_de_champ).to be_present
|
||||||
|
expect(procedure.draft_revision.types_de_champ).to be_present
|
||||||
|
expect(procedure.draft_revision.types_de_champ.first.libelle).to eq('libelle 1')
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the procedure has dossiers' do
|
||||||
|
let(:dossier_draft) { create(:dossier, :brouillon, procedure: procedure) }
|
||||||
|
let(:dossier_submitted) { create(:dossier, :en_construction, procedure: procedure) }
|
||||||
|
|
||||||
|
before { [dossier_draft, dossier_submitted] }
|
||||||
|
|
||||||
|
it 'enqueues rebase jobs for draft dossiers' do
|
||||||
|
subject
|
||||||
|
expect(DossierRebaseJob).to have_been_enqueued.with(dossier_draft)
|
||||||
|
expect(DossierRebaseJob).not_to have_been_enqueued.with(dossier_submitted)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "#unpublish!" do
|
describe "#unpublish!" do
|
||||||
let(:procedure) { create(:procedure, :published) }
|
let(:procedure) { create(:procedure, :published) }
|
||||||
let(:now) { Time.zone.now.beginning_of_minute }
|
let(:now) { Time.zone.now.beginning_of_minute }
|
||||||
|
|
Loading…
Reference in a new issue