models: fix touch not propagating when using nested attributes
Sometimes, when using nested attributes, touch doesn’t propagate to parent relationships. (see https://github.com/rails/rails/issues/26726) Specifically, this happens in our app when updating a dossier with only new attachements (but without changing the value of any fields). To work around this, we need to define the parent relationship explicitely. This is good practice anyway. Fix #3906
This commit is contained in:
parent
52d672486e
commit
51aacabf13
7 changed files with 57 additions and 12 deletions
|
@ -1,7 +1,7 @@
|
|||
class Avis < ApplicationRecord
|
||||
include EmailSanitizableConcern
|
||||
|
||||
belongs_to :dossier, touch: true
|
||||
belongs_to :dossier, inverse_of: :avis, touch: true
|
||||
belongs_to :gestionnaire
|
||||
belongs_to :claimant, class_name: 'Gestionnaire'
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
class Champ < ApplicationRecord
|
||||
belongs_to :dossier, touch: true
|
||||
belongs_to :dossier, inverse_of: :champs, touch: true
|
||||
belongs_to :type_de_champ, inverse_of: :champ
|
||||
belongs_to :parent, class_name: 'Champ'
|
||||
has_many :commentaires
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
class Commentaire < ApplicationRecord
|
||||
belongs_to :dossier, touch: true
|
||||
belongs_to :dossier, inverse_of: :commentaires, touch: true
|
||||
belongs_to :piece_justificative
|
||||
|
||||
belongs_to :user
|
||||
|
|
|
@ -19,18 +19,18 @@ class Dossier < ApplicationRecord
|
|||
has_one :individual, dependent: :destroy
|
||||
has_one :attestation, dependent: :destroy
|
||||
|
||||
has_many :pieces_justificatives, dependent: :destroy
|
||||
has_many :pieces_justificatives, inverse_of: :dossier, dependent: :destroy
|
||||
has_one_attached :justificatif_motivation
|
||||
|
||||
has_many :champs, -> { root.public_only.ordered }, dependent: :destroy
|
||||
has_many :champs_private, -> { root.private_only.ordered }, class_name: 'Champ', dependent: :destroy
|
||||
has_many :commentaires, dependent: :destroy
|
||||
has_many :champs, -> { root.public_only.ordered }, inverse_of: :dossier, dependent: :destroy
|
||||
has_many :champs_private, -> { root.private_only.ordered }, class_name: 'Champ', inverse_of: :dossier, dependent: :destroy
|
||||
has_many :commentaires, inverse_of: :dossier, dependent: :destroy
|
||||
has_many :invites, dependent: :destroy
|
||||
has_many :follows, -> { active }
|
||||
has_many :previous_follows, -> { inactive }, class_name: 'Follow'
|
||||
has_many :followers_gestionnaires, through: :follows, source: :gestionnaire
|
||||
has_many :previous_followers_gestionnaires, -> { distinct }, through: :previous_follows, source: :gestionnaire
|
||||
has_many :avis, dependent: :destroy
|
||||
has_many :avis, inverse_of: :dossier, dependent: :destroy
|
||||
|
||||
has_many :dossier_operation_logs, dependent: :destroy
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
class PieceJustificative < ApplicationRecord
|
||||
belongs_to :dossier, touch: true
|
||||
belongs_to :dossier, inverse_of: :pieces_justificatives, touch: true
|
||||
belongs_to :type_de_piece_justificative
|
||||
has_one :commentaire
|
||||
|
||||
|
|
|
@ -386,9 +386,11 @@ describe Users::DossiersController, type: :controller do
|
|||
|
||||
describe '#update_brouillon' do
|
||||
before { sign_in(user) }
|
||||
|
||||
let!(:dossier) { create(:dossier, user: user) }
|
||||
let(:first_champ) { dossier.champs.first }
|
||||
let(:value) { 'beautiful value' }
|
||||
let(:now) { Time.zone.parse('01/01/2100') }
|
||||
let(:submit_payload) do
|
||||
{
|
||||
id: dossier.id,
|
||||
|
@ -402,7 +404,11 @@ describe Users::DossiersController, type: :controller do
|
|||
end
|
||||
let(:payload) { submit_payload }
|
||||
|
||||
subject { patch :update_brouillon, params: payload }
|
||||
subject do
|
||||
Timecop.freeze(now) do
|
||||
patch :update_brouillon, params: payload
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the dossier cannot be updated by the user' do
|
||||
let!(:dossier) { create(:dossier, :en_instruction, user: user) }
|
||||
|
@ -421,6 +427,7 @@ describe Users::DossiersController, type: :controller do
|
|||
|
||||
expect(response).to redirect_to(merci_dossier_path(dossier))
|
||||
expect(first_champ.reload.value).to eq('beautiful value')
|
||||
expect(dossier.reload.updated_at.year).to eq(2100)
|
||||
expect(dossier.reload.state).to eq(Dossier.states.fetch(:en_construction))
|
||||
end
|
||||
|
||||
|
@ -549,9 +556,15 @@ describe Users::DossiersController, type: :controller do
|
|||
|
||||
describe '#update' do
|
||||
before { sign_in(user) }
|
||||
let!(:dossier) { create(:dossier, :en_construction, user: user) }
|
||||
|
||||
let(:procedure) { create(:procedure, :published, :with_type_de_champ, :with_piece_justificative) }
|
||||
let!(:dossier) { create(:dossier, :en_construction, user: user, procedure: procedure) }
|
||||
let(:first_champ) { dossier.champs.first }
|
||||
let(:piece_justificative_champ) { dossier.champs.last }
|
||||
let(:value) { 'beautiful value' }
|
||||
let(:file) { Rack::Test::UploadedFile.new("./spec/fixtures/files/piece_justificative_0.pdf", 'application/pdf') }
|
||||
let(:now) { Time.zone.parse('01/01/2100') }
|
||||
|
||||
let(:submit_payload) do
|
||||
{
|
||||
id: dossier.id,
|
||||
|
@ -565,7 +578,11 @@ describe Users::DossiersController, type: :controller do
|
|||
end
|
||||
let(:payload) { submit_payload }
|
||||
|
||||
subject { patch :update, params: payload }
|
||||
subject do
|
||||
Timecop.freeze(now) do
|
||||
patch :update, params: payload
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the dossier cannot be updated by the user' do
|
||||
let!(:dossier) { create(:dossier, :en_instruction, user: user) }
|
||||
|
@ -584,8 +601,28 @@ describe Users::DossiersController, type: :controller do
|
|||
|
||||
expect(response).to redirect_to(demande_dossier_path(dossier))
|
||||
expect(first_champ.reload.value).to eq('beautiful value')
|
||||
expect(dossier.reload.updated_at.year).to eq(2100)
|
||||
expect(dossier.reload.state).to eq(Dossier.states.fetch(:en_construction))
|
||||
end
|
||||
|
||||
context 'when only files champs are modified' do
|
||||
let(:submit_payload) do
|
||||
{
|
||||
id: dossier.id,
|
||||
dossier: {
|
||||
champs_attributes: {
|
||||
id: piece_justificative_champ.id,
|
||||
piece_justificative_file: file
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'updates the dossier modification date' do
|
||||
subject
|
||||
expect(dossier.reload.updated_at.year).to eq(2100)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the update fails' do
|
||||
|
|
|
@ -127,6 +127,14 @@ FactoryBot.define do
|
|||
end
|
||||
end
|
||||
|
||||
trait :with_piece_justificative do
|
||||
after(:build) do |procedure, _evaluator|
|
||||
type_de_champ = create(:type_de_champ_piece_justificative)
|
||||
procedure.types_de_champ << type_de_champ
|
||||
end
|
||||
end
|
||||
|
||||
# Deprecated
|
||||
trait :with_two_type_de_piece_justificative do
|
||||
after(:build) do |procedure, _evaluator|
|
||||
rib = create(:type_de_piece_justificative, :rib, order_place: 1)
|
||||
|
|
Loading…
Reference in a new issue