b4um_generators 0.2.10 → 0.2.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +2 -2
  3. data/README.de.md +127 -1
  4. data/README.md +126 -1
  5. data/lib/b4um_generators/version.rb +1 -1
  6. data/lib/generators/b4um/attachment/attachment_generator.rb +190 -29
  7. data/lib/generators/b4um/authentication/authentication_generator.rb +63 -0
  8. data/lib/generators/b4um/help/help_generator.rb +100 -3
  9. data/lib/generators/b4um/in_place/in_place_generator.rb +1231 -0
  10. data/lib/generators/b4um/in_place/templates/_flash.html.erb +15 -0
  11. data/lib/generators/b4um/in_place/templates/b4um_in_place_helper.rb +7 -0
  12. data/lib/generators/b4um/in_place/templates/display_attachment.html.erb.tt +154 -0
  13. data/lib/generators/b4um/in_place/templates/display_attachments.html.erb.tt +165 -0
  14. data/lib/generators/b4um/in_place/templates/display_boolean.html.erb.tt +18 -0
  15. data/lib/generators/b4um/in_place/templates/display_number.html.erb.tt +18 -0
  16. data/lib/generators/b4um/in_place/templates/display_radio.html.erb.tt +23 -0
  17. data/lib/generators/b4um/in_place/templates/display_rich_text.html.erb.tt +123 -0
  18. data/lib/generators/b4um/in_place/templates/display_select.html.erb.tt +23 -0
  19. data/lib/generators/b4um/in_place/templates/display_text.html.erb.tt +18 -0
  20. data/lib/generators/b4um/in_place/templates/edit_attachment.html.erb.tt +83 -0
  21. data/lib/generators/b4um/in_place/templates/edit_attachments.html.erb.tt +65 -0
  22. data/lib/generators/b4um/in_place/templates/edit_boolean.html.erb.tt +32 -0
  23. data/lib/generators/b4um/in_place/templates/edit_number.html.erb.tt +26 -0
  24. data/lib/generators/b4um/in_place/templates/edit_radio.html.erb.tt +32 -0
  25. data/lib/generators/b4um/in_place/templates/edit_rich_text.html.erb.tt +25 -0
  26. data/lib/generators/b4um/in_place/templates/edit_select.html.erb.tt +28 -0
  27. data/lib/generators/b4um/in_place/templates/edit_text.html.erb.tt +25 -0
  28. data/lib/generators/b4um/in_place/templates/in_place.css +935 -0
  29. data/lib/generators/b4um/in_place/templates/in_place_controller.js +115 -0
  30. data/lib/generators/b4um/install/install_generator.rb +18 -13
  31. data/lib/generators/b4um/install/templates/_flash.html.erb +15 -0
  32. data/lib/generators/b4um/install/templates/_footer.html.erb +6 -1
  33. data/lib/generators/b4um/install/templates/b4um/forms.css +127 -0
  34. data/lib/generators/b4um/install/templates/image_lightbox_controller.js +29 -0
  35. data/lib/generators/b4um/install/templates/rich_text_controller.js +22 -0
  36. data/lib/generators/b4um/install/templates/scroll_to_top_controller.js +12 -0
  37. data/lib/generators/b4um/scaffold/scaffold_generator.rb +106 -0
  38. data/lib/generators/b4um/scaffold/templates/_form.html.erb.tt +29 -0
  39. data/lib/generators/b4um/scaffold/templates/_resource.html.erb.tt +35 -0
  40. data/lib/generators/b4um/scaffold/templates/_table.html.erb.tt +31 -0
  41. data/lib/generators/b4um/trix/trix_generator.rb +104 -6
  42. metadata +27 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bedf093ab3a868c663ba73bc843bfd9e262dde6511058cbeeafb48b2e48c228d
4
- data.tar.gz: 64ae08a60ec9482ba1040b738c3a92e24da26c079586f74673e3aa7b6c323f4f
3
+ metadata.gz: b1f1050f028cad2eefaf3b2643268bd1e55267aefd8029a8c286e56a5f64b27d
4
+ data.tar.gz: be01b49c59c57796e2f9d83ae1d0f065119edc374a2addd64166063a17c6bc15
5
5
  SHA512:
6
- metadata.gz: effd259d2314e5450df3104327b54e5bd7aa803879897bcd8ec321a682b2e54466df294607633bcc0c4f452cb5ce1e644eb56374275ad77b86720111de1e8be2
7
- data.tar.gz: f5b4d6ceaf22362d380413be06194cc7b1e870b316737bf31089dc290b85ba303d7a7e294ccc1696424567b36f0d9b1ec2becc1921307d475c940c1140046bbc
6
+ metadata.gz: 107f73e822050fbe81d7a9e12419a988478d63ba929215e6aad778fcc4e8b37a93695b778b95b881b3476eda91c5dec04b497648ad6f1038c011971bfcb89bcf
7
+ data.tar.gz: 94552c06de7aba5a9aa211f576447fa8a85dc45fb5eaee2158278d57f1ab8e3cc21727e94d21d2fac36fc356155cba4c2c07bbd7bed55f39cc9a6b4db369e05d
data/.rubocop.yml CHANGED
@@ -15,14 +15,14 @@ Style/StringLiteralsInInterpolation:
15
15
  EnforcedStyle: double_quotes
16
16
 
17
17
  Metrics/MethodLength:
18
- Max: 650
18
+ Max: 1050
19
19
 
20
20
  Metrics/BlockLength:
21
21
  Exclude:
22
22
  - 'spec/**/*'
23
23
 
24
24
  Metrics/ClassLength:
25
- Max: 650
25
+ Max: 1050
26
26
 
27
27
  Metrics/AbcSize:
28
28
  Max: 100
data/README.de.md CHANGED
@@ -82,6 +82,7 @@ b4um:pagination
82
82
  b4um:infinite_scroll
83
83
  b4um:search
84
84
  b4um:comments
85
+ b4um:in_place
85
86
  b4um:authentication
86
87
  b4um:trix
87
88
  b4um:readable
@@ -114,6 +115,8 @@ Der Scaffold-Generator bietet:
114
115
  - Index-, Show-, New- und Edit-Views
115
116
  - Standardmäßig ein Bento-Index-Layout
116
117
  - Optionales Tabellen-Index-Layout
118
+ - Select-Felder mit eigenen Anzeigebezeichnungen
119
+ - Radio-Felder mit eigenen Anzeigebezeichnungen
117
120
  - Automatischen Navigationseintrag
118
121
  - Aktiven Navigationszustand
119
122
  - Anzeige von Formular-Validierungsfehlern
@@ -121,6 +124,45 @@ Der Scaffold-Generator bietet:
121
124
  - Unterstützung für Passwortfelder
122
125
  - Optionale lesbare URL-Parameter
123
126
 
127
+ ### Select- und Radio-Felder
128
+
129
+ Der Scaffold-Generator kann String-Attribute als Select- oder Radio-Felder mit eigenen Anzeigebezeichnungen erzeugen.
130
+
131
+ Für ein Select-Feld verwende:
132
+
133
+ ```text
134
+ --select='FIELD:VALUE=LABEL,VALUE=LABEL'
135
+ ```
136
+
137
+ Beispiel:
138
+
139
+ ```bash
140
+ bin/rails generate b4um:scaffold Product name:string status:string --select='status:Active=Aktiv,Inactive=Inaktiv'
141
+ ```
142
+
143
+ Für Radio-Buttons verwende:
144
+
145
+ ```text
146
+ --radio='FIELD:VALUE=LABEL,VALUE=LABEL'
147
+ ```
148
+
149
+ Beispiel:
150
+
151
+ ```bash
152
+ bin/rails generate b4um:scaffold Product name:string condition:string --radio='condition:new=Neu,used=Gebraucht,refurbished=Generalüberholt'
153
+ ```
154
+
155
+ Beide Optionen können für unterschiedliche Felder miteinander kombiniert werden:
156
+
157
+ ```bash
158
+ bin/rails generate b4um:scaffold Product name:string status:string condition:string --select='status:Active=Aktiv,Inactive=Inaktiv' --radio='condition:new=Neu,used=Gebraucht'
159
+ ```
160
+
161
+ Die konfigurierten Werte werden in der Datenbank gespeichert. In Formularen, Ressourcen-Views und Tabellen-Layouts
162
+ werden dagegen die zugehörigen Anzeigebezeichnungen dargestellt.
163
+
164
+ Dasselbe Feld kann nicht gleichzeitig `--select` und `--radio` verwenden.
165
+
124
166
  ### Bento-Index
125
167
 
126
168
  Der standardmäßige Scaffold-Index verwendet das responsive b4um-Bento-Kartenlayout.
@@ -690,6 +732,90 @@ Bestehende b4um-Comments-Controller werden automatisch erweitert.
690
732
  Unbekannte benutzerdefinierte Comments-Controller bleiben unverändert und führen dazu, dass der Generator abbricht,
691
733
  anstatt eigenen Code zu überschreiben.
692
734
 
735
+ ## In-place Editing
736
+
737
+ Füge Feldern einer bestehenden b4um-Ressource eine direkte Bearbeitung hinzu:
738
+
739
+ ```bash
740
+ bin/rails generate b4um:in_place MODEL FIELD [FIELD ...]
741
+ ```
742
+
743
+ Beispiel für ein einzelnes Feld:
744
+
745
+ ```bash
746
+ bin/rails generate b4um:in_place Product name
747
+ ```
748
+
749
+ Mehrere Felder können in einem Durchlauf hinzugefügt werden:
750
+
751
+ ```bash
752
+ bin/rails generate b4um:in_place Product name price status
753
+ ```
754
+
755
+ Modell, Controller und Resource-Routen müssen bereits vorhanden sein.
756
+
757
+ Der Generator erkennt die vorhandenen Feldtypen automatisch und erstellt die passenden Editoren.
758
+
759
+ Unterstützte Felder sind:
760
+
761
+ - String- und Text-Felder
762
+ - Numerische und Decimal-Felder
763
+ - Boolean-Felder
764
+ - Action-Text-Rich-Text-Felder
765
+ - Einzelne Active-Storage-Bild-Attachments
766
+ - Mehrere Active-Storage-Bild-Attachments
767
+
768
+ ### Select-Felder
769
+
770
+ Ein Feld kann mit `--select` als Auswahlliste dargestellt werden:
771
+
772
+ ```bash
773
+ bin/rails generate b4um:in_place Product status --select='status:Active=Aktiv,Inactive=Inaktiv'
774
+ ```
775
+
776
+ Der Wert vor `=` wird in der Datenbank gespeichert. Der optionale Wert nach `=` wird als sichtbare Beschriftung
777
+ verwendet.
778
+
779
+ Zum Beispiel speichert `Active=Aktiv` den Wert `Active`, während `Aktiv` angezeigt wird.
780
+
781
+ ### Radio-Felder
782
+
783
+ Ein Feld kann mit `--radio` als Gruppe von Radio-Buttons dargestellt werden:
784
+
785
+ ```bash
786
+ bin/rails generate b4um:in_place Product condition --radio='condition:new=Neu,used=Gebraucht,refurbished=Generalüberholt'
787
+ ```
788
+
789
+ Für Radio-Felder gilt dieselbe Wert- und Beschriftungssyntax wie für `--select`.
790
+
791
+ ### Verhalten der In-place-Bearbeitung
792
+
793
+ Die generierte In-place-Bearbeitung bietet:
794
+
795
+ - Bearbeitung mit Turbo Frames ohne zusätzliches In-place-Editing-Gem
796
+ - Direkte Bearbeitung innerhalb des bestehenden Ressourcen-Layouts
797
+ - Speichern von Text- und Rich-Text-Feldern beim Klick außerhalb des Editors
798
+ - Sofortiges Speichern von Select-, Radio- und Boolean-Feldern
799
+ - Bearbeitung einzelner und mehrerer Bild-Attachments
800
+ - Entfernen vorhandener Bild-Attachments
801
+ - Validierungsfehler direkt im Editor
802
+ - Sofortige Aktualisierung der Flash-Meldung nach erfolgreicher Änderung
803
+ - Mehrere Felder in einem Generator-Durchlauf
804
+ - Nachträgliches Hinzufügen weiterer Felder
805
+ - Sichere wiederholte Ausführung des Generators
806
+
807
+ ### Authentifizierung
808
+
809
+ Die In-place-Bearbeitung integriert sich automatisch in die b4um-Authentifizierung.
810
+
811
+ Ohne Authentifizierung können die generierten In-place-Felder bearbeitet werden.
812
+
813
+ Wenn die b4um-Authentifizierung installiert ist, wird die In-place-Bearbeitung auf angemeldete Benutzer beschränkt und
814
+ die zugehörigen Controller-Actions werden mit `require_login` geschützt.
815
+
816
+ Die Authentifizierung kann vor oder nach der In-place-Bearbeitung installiert werden. Die Generatoren aktualisieren die
817
+ Integration in beiden Installationsreihenfolgen automatisch.
818
+
693
819
  ## Trix und Rich Text
694
820
 
695
821
  Füge einer bestehenden b4um-Ressource Rails Action Text mit Trix hinzu:
@@ -978,7 +1104,7 @@ wird.
978
1104
 
979
1105
  ## Version
980
1106
 
981
- Aktuelle Version: `0.2.6`
1107
+ Aktuelle Version: `0.2.14`
982
1108
 
983
1109
  ## Autor
984
1110
 
data/README.md CHANGED
@@ -80,6 +80,7 @@ b4um:pagination
80
80
  b4um:infinite_scroll
81
81
  b4um:search
82
82
  b4um:comments
83
+ b4um:in_place
83
84
  b4um:authentication
84
85
  b4um:trix
85
86
  b4um:readable
@@ -112,6 +113,8 @@ The scaffold generator provides:
112
113
  - Index, show, new and edit views
113
114
  - Bento index layout by default
114
115
  - Optional table index layout
116
+ - Select fields with custom labels
117
+ - Radio fields with custom labels
115
118
  - Automatic navigation entry
116
119
  - Active navigation state
117
120
  - Form validation errors
@@ -119,6 +122,45 @@ The scaffold generator provides:
119
122
  - Password field support
120
123
  - Optional readable URL parameters
121
124
 
125
+ ### Select and Radio Fields
126
+
127
+ The scaffold generator can render string attributes as select or radio fields with custom display labels.
128
+
129
+ For a select field, use:
130
+
131
+ ```text
132
+ --select='FIELD:VALUE=LABEL,VALUE=LABEL'
133
+ ```
134
+
135
+ Example:
136
+
137
+ ```bash
138
+ bin/rails generate b4um:scaffold Product name:string status:string --select='status:Active=Aktiv,Inactive=Inaktiv'
139
+ ```
140
+
141
+ For radio buttons, use:
142
+
143
+ ```text
144
+ --radio='FIELD:VALUE=LABEL,VALUE=LABEL'
145
+ ```
146
+
147
+ Example:
148
+
149
+ ```bash
150
+ bin/rails generate b4um:scaffold Product name:string condition:string --radio='condition:new=Neu,used=Gebraucht,refurbished=Generalüberholt'
151
+ ```
152
+
153
+ Both options can be combined for different fields:
154
+
155
+ ```bash
156
+ bin/rails generate b4um:scaffold Product name:string status:string condition:string --select='status:Active=Aktiv,Inactive=Inaktiv' --radio='condition:new=Neu,used=Gebraucht'
157
+ ```
158
+
159
+ The configured values are stored in the database, while the labels are displayed in forms, resource views and table
160
+ layouts.
161
+
162
+ A field cannot use both `--select` and `--radio`.
163
+
122
164
  ### Bento Index
123
165
 
124
166
  The default scaffold index uses the responsive b4um Bento card layout.
@@ -685,6 +727,89 @@ Existing b4um comments controllers are extended automatically.
685
727
  Unknown custom comments controllers are left unchanged and cause the generator to stop instead of overwriting custom
686
728
  code.
687
729
 
730
+ ## In-place Editing
731
+
732
+ Add in-place editing to fields of an existing b4um resource:
733
+
734
+ ```bash
735
+ bin/rails generate b4um:in_place MODEL FIELD [FIELD ...]
736
+ ```
737
+
738
+ Example for a single field:
739
+
740
+ ```bash
741
+ bin/rails generate b4um:in_place Product name
742
+ ```
743
+
744
+ Multiple fields can be added in one run:
745
+
746
+ ```bash
747
+ bin/rails generate b4um:in_place Product name price status
748
+ ```
749
+
750
+ The model, controller and resource routes must already exist.
751
+
752
+ The generator detects the existing field types and creates the appropriate editors.
753
+
754
+ Supported fields include:
755
+
756
+ - String and text fields
757
+ - Numeric and decimal fields
758
+ - Boolean fields
759
+ - Action Text rich-text fields
760
+ - Active Storage single image attachments
761
+ - Active Storage multiple image attachments
762
+
763
+ ### Select Fields
764
+
765
+ A field can be rendered as a select list with `--select`:
766
+
767
+ ```bash
768
+ bin/rails generate b4um:in_place Product status --select='status:Active=Aktiv,Inactive=Inaktiv'
769
+ ```
770
+
771
+ The value before `=` is stored in the database. The optional value after `=` is used as the displayed label.
772
+
773
+ For example, `Active=Aktiv` stores `Active` while displaying `Aktiv`.
774
+
775
+ ### Radio Fields
776
+
777
+ A field can be rendered as radio buttons with `--radio`:
778
+
779
+ ```bash
780
+ bin/rails generate b4um:in_place Product condition --radio='condition:new=Neu,used=Gebraucht,refurbished=Generalüberholt'
781
+ ```
782
+
783
+ The same value and label syntax used by `--select` applies to radio fields.
784
+
785
+ ### In-place Editing Behavior
786
+
787
+ Generated in-place editing provides:
788
+
789
+ - Turbo Frame based editing without an additional in-place editing gem
790
+ - Editing directly inside the existing resource layout
791
+ - Outside-click saving for text and rich-text fields
792
+ - Immediate saving for select, radio and boolean fields
793
+ - Single and multiple image attachment editing
794
+ - Removal of existing image attachments
795
+ - Inline validation errors
796
+ - Immediate flash-message updates after successful changes
797
+ - Multiple fields in one generator run
798
+ - Additional fields in later generator runs
799
+ - Safe repeated generator runs
800
+
801
+ ### Authentication
802
+
803
+ In-place editing integrates automatically with b4um authentication.
804
+
805
+ Without authentication, generated in-place fields are editable.
806
+
807
+ When b4um authentication is installed, in-place editing is restricted to logged-in users and the corresponding
808
+ controller actions are protected with `require_login`.
809
+
810
+ Authentication can be installed either before or after in-place editing. The generators update the integration
811
+ automatically in both installation orders.
812
+
688
813
  ## Trix and Rich Text
689
814
 
690
815
  Add Rails Action Text with Trix to an existing b4um resource:
@@ -970,7 +1095,7 @@ The gem can be tested locally by referencing the repository with `path:` from a
970
1095
 
971
1096
  ## Version
972
1097
 
973
- Current version: `0.2.7`
1098
+ Current version: `0.2.14`
974
1099
 
975
1100
  ## Author
976
1101
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module B4umGenerators
4
- VERSION = "0.2.10"
4
+ VERSION = "0.2.14"
5
5
  end
@@ -110,13 +110,18 @@ module B4um
110
110
  def update_single_attachment_params
111
111
  content = File.read(controller_path)
112
112
 
113
- return if attachment_permitted?(content)
113
+ update_single_permitted_params(content)
114
+ update_single_attachment_action
115
+ end
116
+
117
+ def update_single_permitted_params(content)
118
+ return if single_attachment_permitted?(content)
114
119
 
115
120
  pattern = /
116
121
  params\.expect\(
117
122
  #{Regexp.escape(file_name)}:\s*
118
123
  \[
119
- (?<attributes>[^\]]*)
124
+ (?<attributes>.*?)
120
125
  \]
121
126
  \)
122
127
  /mx
@@ -124,9 +129,88 @@ module B4um
124
129
  return unless content.match?(pattern)
125
130
 
126
131
  gsub_file(controller_path, pattern) do |match|
132
+ match_data = pattern.match(match)
133
+ attributes = match_data[:attributes]
134
+
135
+ insertion = ":#{attachment}, :remove_#{attachment}"
136
+
137
+ normalized_attributes =
138
+ attributes
139
+ .strip
140
+ .gsub(/\s+,/, ",")
141
+
142
+ updated_attributes =
143
+ if normalized_attributes.match?(/\w+:\s*\[/)
144
+ normalized_attributes.sub(
145
+ /(?=\w+:\s*\[)/,
146
+ "#{insertion}, "
147
+ )
148
+ else
149
+ "#{normalized_attributes}, #{insertion}"
150
+ end
151
+
127
152
  match.sub(
128
- /\]\)$/,
129
- ", :#{attachment}])"
153
+ attributes,
154
+ " #{updated_attributes} "
155
+ )
156
+ end
157
+ end
158
+
159
+ def single_attachment_permitted?(content)
160
+ content.include?(
161
+ ":#{attachment}, :remove_#{attachment}"
162
+ )
163
+ end
164
+
165
+ def update_single_attachment_action
166
+ content = File.read(controller_path)
167
+
168
+ return if content.include?(
169
+ "remove_#{attachment} = update_params.delete(\"remove_#{attachment}\")"
170
+ )
171
+
172
+ if content.include?(" update_params = #{file_name}_params\n")
173
+ insert_into_file(
174
+ controller_path,
175
+ " remove_#{attachment} = update_params.delete(\"remove_#{attachment}\")\n",
176
+ after: " update_params = #{file_name}_params\n"
177
+ )
178
+ else
179
+ setup = [
180
+ " def update",
181
+ " update_params = #{file_name}_params",
182
+ " remove_#{attachment} = update_params.delete(\"remove_#{attachment}\")",
183
+ "",
184
+ " respond_to do |format|",
185
+ ""
186
+ ].join("\n")
187
+
188
+ gsub_file(
189
+ controller_path,
190
+ " def update\n respond_to do |format|\n",
191
+ setup
192
+ )
193
+ end
194
+
195
+ content = File.read(controller_path)
196
+
197
+ if content.include?(" if @#{file_name}.update(update_params)\n")
198
+ insert_into_file(
199
+ controller_path,
200
+ " @#{file_name}.#{attachment}.purge if remove_#{attachment} == \"1\"\n",
201
+ after: " if @#{file_name}.update(update_params)\n"
202
+ )
203
+ else
204
+ attachment_handling = [
205
+ " if @#{file_name}.update(update_params)",
206
+ " @#{file_name}.#{attachment}.purge if remove_#{attachment} == \"1\"",
207
+ ""
208
+ ].join("\n")
209
+
210
+ gsub_file(
211
+ controller_path,
212
+ " if @#{file_name}.update(#{file_name}_params)\n",
213
+ attachment_handling
130
214
  )
131
215
  end
132
216
  end
@@ -141,23 +225,59 @@ module B4um
141
225
  def update_multiple_permitted_params(content)
142
226
  return if multiple_attachment_permitted?(content)
143
227
 
144
- pattern = /
228
+ params_method_pattern = /
229
+ def\s+#{Regexp.escape(file_name)}_params
230
+ (?<body>.*?)
231
+ ^\s*end
232
+ /mx
233
+
234
+ params_method = content[params_method_pattern, 0]
235
+
236
+ unless params_method
237
+ raise Thor::Error,
238
+ "Could not find #{file_name}_params in #{controller_path}"
239
+ end
240
+
241
+ expect_pattern = /
145
242
  params\.expect\(
146
243
  #{Regexp.escape(file_name)}:\s*
147
244
  \[
148
- (?<attributes>[^\]]*)
245
+ (?<attributes>.*)
149
246
  \]
150
247
  \)
151
248
  /mx
152
249
 
153
- return unless content.match?(pattern)
250
+ match_data = expect_pattern.match(params_method)
154
251
 
155
- gsub_file(controller_path, pattern) do |match|
156
- match.sub(
157
- /\]\)$/,
158
- ", #{attachment}: [], remove_#{attachment}_ids: []])"
159
- )
252
+ unless match_data
253
+ raise Thor::Error,
254
+ "Could not find params.expect for #{file_name} in #{controller_path}"
160
255
  end
256
+
257
+ normalized_attributes =
258
+ match_data[:attributes]
259
+ .strip
260
+ .gsub(/\s+,/, ",")
261
+
262
+ updated_attributes =
263
+ "#{normalized_attributes}, " \
264
+ "#{attachment}: [], " \
265
+ "remove_#{attachment}_ids: []"
266
+
267
+ updated_params_method =
268
+ params_method.sub(
269
+ match_data[0],
270
+ match_data[0].sub(
271
+ match_data[:attributes],
272
+ " #{updated_attributes} "
273
+ )
274
+ )
275
+
276
+ gsub_file(
277
+ controller_path,
278
+ params_method,
279
+ updated_params_method
280
+ )
161
281
  end
162
282
 
163
283
  def multiple_attachment_permitted?(content)
@@ -173,24 +293,43 @@ module B4um
173
293
  "new_#{attachment} = update_params.delete(\"#{attachment}\")"
174
294
  )
175
295
 
296
+ unless content.include?(" update_params = #{file_name}_params\n")
297
+ gsub_file(
298
+ controller_path,
299
+ " def update\n respond_to do |format|\n",
300
+ [
301
+ " def update",
302
+ " update_params = #{file_name}_params",
303
+ "",
304
+ " respond_to do |format|",
305
+ ""
306
+ ].join("\n")
307
+ )
308
+ end
309
+
176
310
  setup = [
177
- " def update",
178
- " update_params = #{file_name}_params",
179
311
  " new_#{attachment} = update_params.delete(\"#{attachment}\")",
180
312
  " remove_#{attachment}_ids = update_params.delete(\"remove_#{attachment}_ids\")",
181
- "",
182
- " respond_to do |format|",
183
313
  ""
184
314
  ].join("\n")
185
315
 
186
- gsub_file(
316
+ insert_into_file(
187
317
  controller_path,
188
- " def update\n respond_to do |format|\n",
189
- setup
318
+ setup,
319
+ after: " update_params = #{file_name}_params\n"
190
320
  )
191
321
 
322
+ content = File.read(controller_path)
323
+
324
+ unless content.include?(" if @#{file_name}.update(update_params)\n")
325
+ gsub_file(
326
+ controller_path,
327
+ " if @#{file_name}.update(#{file_name}_params)\n",
328
+ " if @#{file_name}.update(update_params)\n"
329
+ )
330
+ end
331
+
192
332
  attachment_handling = [
193
- " if @#{file_name}.update(update_params)",
194
333
  " @#{file_name}.#{attachment}.attach(new_#{attachment}) if new_#{attachment}.present?",
195
334
  "",
196
335
  " if remove_#{attachment}_ids.present?",
@@ -201,10 +340,10 @@ module B4um
201
340
  ""
202
341
  ].join("\n")
203
342
 
204
- gsub_file(
343
+ insert_into_file(
205
344
  controller_path,
206
- " if @#{file_name}.update(#{file_name}_params)\n",
207
- attachment_handling
345
+ attachment_handling,
346
+ after: " if @#{file_name}.update(update_params)\n"
208
347
  )
209
348
  end
210
349
 
@@ -439,12 +578,34 @@ module B4um
439
578
  <%= "hidden" unless #{file_name}.#{attachment}.attached? %>>
440
579
 
441
580
  <% if #{file_name}.#{attachment}.attached? %>
442
- <%= image_tag #{file_name}.#{attachment},
443
- class: "form-image-preview__image",
444
- alt: #{file_name}.#{attachment}.filename.to_s,
445
- data: {
446
- image_preview_target: "image"
447
- } %>
581
+ <div class="form-image-preview__item"
582
+ role="button"
583
+ tabindex="0"
584
+ aria-pressed="false"
585
+ data-image-preview-target="existingItem"
586
+ data-action="click->image-preview#toggleRemoval keydown->image-preview#toggleRemovalWithKeyboard">
587
+
588
+ <%= image_tag #{file_name}.#{attachment},
589
+ class: "form-image-preview__image",
590
+ alt: #{file_name}.#{attachment}.filename.to_s,
591
+ data: {
592
+ image_preview_target: "image"
593
+ } %>
594
+
595
+ <%= check_box_tag(
596
+ "#{file_name}[remove_#{attachment}]",
597
+ "1",
598
+ false,
599
+ class: "form-image-preview__remove-checkbox",
600
+ data: {
601
+ image_preview_target: "removeCheckbox"
602
+ }
603
+ ) %>
604
+
605
+ <div class="form-image-preview__remove-status">
606
+ Will be removed
607
+ </div>
608
+ </div>
448
609
  <% else %>
449
610
  <img class="form-image-preview__image"
450
611
  data-image-preview-target="image"