From c98021e58af472106e7f6f574b66d7acbe90b369 Mon Sep 17 00:00:00 2001 From: Colin Darie Date: Mon, 28 Nov 2022 11:38:28 +0100 Subject: [PATCH] chore(attachment): input name attribute follows form object name for nested attributes --- app/components/attachment/edit_component.rb | 8 ++++++-- app/components/attachment/multiple_component.rb | 4 +++- .../multiple_component.html.haml | 4 ++-- .../piece_justificative_component.html.haml | 2 +- .../titre_identite_component.html.haml | 2 +- spec/components/attachment/edit_component_spec.rb | 14 ++++++++++++++ .../piece_justificative_component_spec.rb | 2 +- 7 files changed, 28 insertions(+), 8 deletions(-) diff --git a/app/components/attachment/edit_component.rb b/app/components/attachment/edit_component.rb index 916520524..c14aadfae 100644 --- a/app/components/attachment/edit_component.rb +++ b/app/components/attachment/edit_component.rb @@ -30,6 +30,10 @@ class Attachment::EditComponent < ApplicationComponent fail ArgumentError, "You must pass an `attachment` kwarg when not using as single attachment like in #{attached_file.name}. Set it to nil for a new attachment." end + # When parent form has nested attributes, pass the form builder object_name + # to correctly infer the input attribute name. + @form_object_name = kwargs.delete(:form_object_name) + verify_initialization!(kwargs) end @@ -81,7 +85,7 @@ class Attachment::EditComponent < ApplicationComponent end def field_name - helpers.field_name(ActiveModel::Naming.param_key(@attached_file.record), attribute_name) + helpers.field_name(@form_object_name || ActiveModel::Naming.param_key(@attached_file.record), attribute_name) end def attribute_name @@ -136,7 +140,7 @@ class Attachment::EditComponent < ApplicationComponent return champ.input_id end - helpers.field_id(@attached_file.record, attribute_name) + helpers.field_id(@form_object_name || @attached_file.record, attribute_name) end def auto_attach_url diff --git a/app/components/attachment/multiple_component.rb b/app/components/attachment/multiple_component.rb index bba56748c..834100ff2 100644 --- a/app/components/attachment/multiple_component.rb +++ b/app/components/attachment/multiple_component.rb @@ -7,6 +7,7 @@ class Attachment::MultipleComponent < ApplicationComponent attr_reader :attached_file attr_reader :attachments attr_reader :champ + attr_reader :form_object_name attr_reader :max attr_reader :user_can_destroy attr_reader :user_can_download @@ -14,9 +15,10 @@ class Attachment::MultipleComponent < ApplicationComponent delegate :count, :empty?, to: :attachments, prefix: true - def initialize(champ:, attached_file:, user_can_download: false, user_can_destroy: true, max: nil) + def initialize(champ:, attached_file:, form_object_name: nil, user_can_download: false, user_can_destroy: true, max: nil) @champ = champ @attached_file = attached_file + @form_object_name = form_object_name @user_can_download = user_can_download @user_can_destroy = user_can_destroy @max = max || DEFAULT_MAX_ATTACHMENTS diff --git a/app/components/attachment/multiple_component/multiple_component.html.haml b/app/components/attachment/multiple_component/multiple_component.html.haml index 4c84e3652..3b6cae9d0 100644 --- a/app/components/attachment/multiple_component/multiple_component.html.haml +++ b/app/components/attachment/multiple_component/multiple_component.html.haml @@ -4,10 +4,10 @@ %ul - each_attachment do |attachment, index| %li{ id: dom_id(attachment) } - = render Attachment::EditComponent.new(champ:, attached_file:, attachment:, index:, as_multiple: true, user_can_destroy:, user_can_download:) + = render Attachment::EditComponent.new(champ:, attached_file:, attachment:, index:, as_multiple: true, user_can_destroy:, user_can_download:, form_object_name:) %div{ id: empty_component_id, class: class_names("hidden": !can_attach_next?) } - = render Attachment::EditComponent.new(champ:, attached_file:, attachment: nil, index: attachments_count, user_can_destroy:) + = render Attachment::EditComponent.new(champ:, attached_file:, attachment: nil, index: attachments_count, user_can_destroy:, form_object_name:) // single poll and refresh message for all attachments = render Attachment::PendingPollComponent.new(attachments: attachments, poll_url:) diff --git a/app/components/editable_champ/piece_justificative_component/piece_justificative_component.html.haml b/app/components/editable_champ/piece_justificative_component/piece_justificative_component.html.haml index 277cdd65b..87a0a8fd0 100644 --- a/app/components/editable_champ/piece_justificative_component/piece_justificative_component.html.haml +++ b/app/components/editable_champ/piece_justificative_component/piece_justificative_component.html.haml @@ -1,7 +1,7 @@ - user_can_destroy = !@champ.mandatory? || @champ.dossier.brouillon? - user_can_download = !@champ.dossier.brouillon? - max = [true, nil].include?(@champ.procedure&.piece_justificative_multiple?) ? Attachment::MultipleComponent::DEFAULT_MAX_ATTACHMENTS : 1 -= render Attachment::MultipleComponent.new(champ: @champ, attached_file: @champ.piece_justificative_file, user_can_destroy:, user_can_download:, max:) do |c| += render Attachment::MultipleComponent.new(champ: @champ, attached_file: @champ.piece_justificative_file, form_object_name: @form.object_name, user_can_destroy:, user_can_download:, max:) do |c| - if @champ.type_de_champ.piece_justificative_template&.attached? - c.with_template do = render partial: "shared/piece_justificative_template", locals: { attachment: @champ.type_de_champ.piece_justificative_template } diff --git a/app/components/editable_champ/titre_identite_component/titre_identite_component.html.haml b/app/components/editable_champ/titre_identite_component/titre_identite_component.html.haml index 3ccccaa75..4a4bfda1a 100644 --- a/app/components/editable_champ/titre_identite_component/titre_identite_component.html.haml +++ b/app/components/editable_champ/titre_identite_component/titre_identite_component.html.haml @@ -2,4 +2,4 @@ - if @champ.type_de_champ.piece_justificative_template&.attached? = render partial: "shared/piece_justificative_template", locals: { attachment: @champ.type_de_champ.piece_justificative_template } -= render Attachment::EditComponent.new(champ: @form.object, attached_file: @champ.piece_justificative_file, attachment: @champ.piece_justificative_file[0], user_can_destroy:) += render Attachment::EditComponent.new(champ: @form.object, attached_file: @champ.piece_justificative_file, attachment: @champ.piece_justificative_file[0], form_object_name: @form.object_name, user_can_destroy:) diff --git a/spec/components/attachment/edit_component_spec.rb b/spec/components/attachment/edit_component_spec.rb index 581ebf622..8fd077374 100644 --- a/spec/components/attachment/edit_component_spec.rb +++ b/spec/components/attachment/edit_component_spec.rb @@ -159,4 +159,18 @@ RSpec.describe Attachment::EditComponent, type: :component do end end end + + describe 'field name inference' do + it "by default generate input name directly form attached file object" do + expect(subject).to have_selector("input[name='champs_titre_identite_champ[piece_justificative_file]']") + end + + context "when a form object_name is provided" do + let(:kwargs) { { form_object_name: "my_form" } } + + it "generate input name from form object name and attached file object" do + expect(subject).to have_selector("input[name='my_form[piece_justificative_file]']") + end + end + end end diff --git a/spec/components/editable_champ/piece_justificative_component/piece_justificative_component_spec.rb b/spec/components/editable_champ/piece_justificative_component/piece_justificative_component_spec.rb index 6d39dbfd2..38838fc2d 100644 --- a/spec/components/editable_champ/piece_justificative_component/piece_justificative_component_spec.rb +++ b/spec/components/editable_champ/piece_justificative_component/piece_justificative_component_spec.rb @@ -1,7 +1,7 @@ describe EditableChamp::PieceJustificativeComponent, type: :component do let(:champ) { create(:champ_piece_justificative, dossier: create(:dossier)) } let(:component) { - described_class.new(form: instance_double(ActionView::Helpers::FormBuilder), champ:) + described_class.new(form: instance_double(ActionView::Helpers::FormBuilder, object_name: "dossier[champs_public_attributes]"), champ:) } let(:subject) {