inline_forms 8.1.11 → 8.1.15

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0e33b151ebeda5706914feaf6ac97bd11b0b379ac8b03435cf9d948c40dbdd9b
4
- data.tar.gz: 975d48a428e045905e0fd29acf6b2d136ec7cc5f4a7825db9c951eb0ab3bba3d
3
+ metadata.gz: 58e6670831f8bce627752b9797371fb20d2f3b14f571a4bc8c879478b71f5ff6
4
+ data.tar.gz: 32fd5f2f3503126e9113d10a3bea9ba23468667f11cc4db8252d78078b101af8
5
5
  SHA512:
6
- metadata.gz: 37d86c5be4e09df199b6d23b8ee91c2488bb98b178b352213dce075234152cc9ef03d119cd2ccd0eb41632d4e6ec5724918d6f2cfdbd70889ed5a0e4b7a959d1
7
- data.tar.gz: 3b40a5c9b0de4707715d43d2186f3d1e4570b7c0cfa17f55f6aa7aa2c151b325bf91a670897ebc3379a1ba086081953f4a0d2f3806a3cd83a13c4fd6149443bb
6
+ metadata.gz: d9e59af7820b05e5ef046c1771a85f37ee1d7dd4ab9affbe0f8e2dfda03fe49db57d9452972406a889f699732165b8117bb56ecdee6c6a5edf9c05b0d14642f8
7
+ data.tar.gz: 55be4d675321e511079de4a362688b664e65dce704dd56ef5929c8db2a286f0fef034312a2572016138808155a18e4f7150472a26aa904adb65e926d762da949
data/CHANGELOG.md CHANGED
@@ -4,6 +4,42 @@ All notable changes to this project are documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [8.1.15] - 2026-05-28
8
+
9
+ ### Fixed
10
+
11
+ - **Post-delete undo on Apartment/Photo (and any model with `rich_text`) left `description` empty.** Undo only reified the parent row; ActionText bodies live in `action_text_rich_texts` and are removed on `destroy`, with separate PaperTrail `destroy` versions. `revert` now also reifies and saves each `ActionText::RichText` destroy snapshot that belonged to the restored parent (Apartment, nested Photo, `FormElementShowcase#description`, etc.).
12
+
13
+ ### Added
14
+
15
+ - **Regression tests:** apartment row destroy+undo with `description` rich text; nested photo destroy+undo with `description` rich text.
16
+
17
+ ## [8.1.14] - 2026-05-28
18
+
19
+ ### Fixed
20
+
21
+ - **`example_app_showcase_row_turbo_test` broke `--example` installs.** The Empty-demo undo regression parsed the undo URL as `/revert/:id`, but member routes are `/form_element_showcases/:id/revert`. The installer gate failed (`131 runs, 1 failure`) and surfaced the misleading “Rails could not create the app 'MyApp', maybe because it is a reserved word…” message even though the app was generated. The test now matches the real path and loads the destroy version from PaperTrail.
22
+
23
+ ## [8.1.13] - 2026-05-28
24
+
25
+ ### Fixed
26
+
27
+ - **Post-delete undo restored the wrong PaperTrail version.** `destroy` stored `@undo_version = @object.versions.last` *before* `destroy`, so the undo link targeted the latest **update** (e.g. a `plain_text_area` edit). `revert` then reified that update — the state *before* the edit — so fields like `body_plain_area` on "Empty demo" came back blank. `@undo_version` is now taken after destroy so undo always targets the `destroy` event snapshot.
28
+
29
+ ### Added
30
+
31
+ - **Regression test** on `FormElementShowcase` "Empty demo": edit `body_plain_area`, delete, undo, assert text and undo URL use the destroy version.
32
+
33
+ ## [8.1.12] - 2026-05-28
34
+
35
+ ### Fixed
36
+
37
+ - **`InlineFormsController#revert` and CanCan `check_authorization`.** `revert` is excluded from `load_and_authorize_resource`, but `authorize!` only ran on some branches — and after `return unless @parent`, so a nil PaperTrail `item` on a destroyed row (or any path that bailed out early) left `@_authorized` unset and raised `CanCan::AuthorizationNotPerformed`. Authorization now runs once at the top of the action via `revert_authorization_subject` (reified record, `ActionText::RichText` parent, live `item`, or an id-only stub for destroyed rows). The post-delete **undo** link in `row_destroyed.html.erb` now requests `turbo_stream` like the versions-panel Restore link, matching the `format.turbo_stream` response.
38
+
39
+ ### Added
40
+
41
+ - **Regression test** `example_app_showcase_row_turbo_test.rb`: destroy + undo revert on `FormElementShowcase`.
42
+
7
43
  ## [8.1.11] - 2026-05-28
8
44
 
9
45
  ### Fixed
@@ -247,8 +247,10 @@ class InlineFormsController < ApplicationController
247
247
  @update_span = params[:update]
248
248
  @object = referenced_object
249
249
  if current_user.role? :superadmin
250
- @undo_version = @object.versions.last
251
250
  @object.destroy
251
+ # Capture after destroy: `.last` before destroy was the latest *update*
252
+ # (e.g. a plain_text_area edit), so undo reified the pre-edit state.
253
+ @undo_version = @object.versions.last
252
254
  respond_to do |format|
253
255
  format.html { render_row_turbo_destroyed } if row_html_turbo_allowed?
254
256
  end
@@ -270,62 +272,116 @@ class InlineFormsController < ApplicationController
270
272
  # below derive from `@parent` for both branches.
271
273
  def revert
272
274
  @update_span = params[:update]
273
- if current_user.role? :superadmin
274
- @version = PaperTrail::Version.find(params[:id])
275
- @object = @version.reify
276
- # PaperTrail::Version#reify returns nil for `create` events because
277
- # there is no prior state to roll back to. The versions list view
278
- # hides the Restore link for `create` rows, but guard here too in
279
- # case a request was bookmarked or replayed: render close on the
280
- # current parent without mutating anything.
281
- if @object.nil?
282
- # reify returns nil for `create` events (no prior state). For a
283
- # rich_text create, reverting means "undo the creation" -> destroy
284
- # the ActionText::RichText row so the parent's field reverts to
285
- # empty (symmetric with reverting an update on a rich_text that
286
- # was first saved empty). For a primary record we never offer
287
- # Restore on `create` in the view; this branch only runs for
288
- # replayed/bookmarked URLs and must remain a no-op response keyed
289
- # off the parent.
290
- item = @version.item
291
- if defined?(ActionText::RichText) && item.is_a?(ActionText::RichText)
292
- @rich_text_record = item
293
- @parent = @rich_text_record.record
294
- return unless @parent
295
- authorize!(:revert, @parent) if cancan_enabled?
296
- @rich_text_record.destroy
297
- @parent.touch if @parent.respond_to?(:touch)
298
- else
299
- @parent = item
300
- return unless @parent
301
- authorize!(:revert, @parent) if cancan_enabled?
302
- end
303
- return unless row_html_turbo_allowed?
304
- respond_to do |format|
305
- format.turbo_stream { render_revert_turbo_streams }
306
- end
307
- return
308
- end
309
- if defined?(ActionText::RichText) && @object.is_a?(ActionText::RichText)
310
- @rich_text_record = @object
275
+ @version = PaperTrail::Version.find(params[:id])
276
+ @parent = revert_authorization_subject(@version)
277
+ authorize!(:revert, @parent || @Klass) if cancan_enabled?
278
+ return head :forbidden unless current_user.role? :superadmin
279
+ return head :not_found unless @parent
280
+
281
+ @object = @version.reify(
282
+ has_many: true,
283
+ has_and_belongs_to_many: true,
284
+ belongs_to: true
285
+ )
286
+ # PaperTrail::Version#reify returns nil for `create` events because
287
+ # there is no prior state to roll back to. The versions list view
288
+ # hides the Restore link for `create` rows, but guard here too in
289
+ # case a request was bookmarked or replayed: render close on the
290
+ # current parent without mutating anything.
291
+ if @object.nil?
292
+ # reify returns nil for `create` events (no prior state). For a
293
+ # rich_text create, reverting means "undo the creation" -> destroy
294
+ # the ActionText::RichText row so the parent's field reverts to
295
+ # empty (symmetric with reverting an update on a rich_text that
296
+ # was first saved empty). For a primary record we never offer
297
+ # Restore on `create` in the view; this branch only runs for
298
+ # replayed/bookmarked URLs and must remain a no-op response keyed
299
+ # off the parent.
300
+ item = @version.item
301
+ if defined?(ActionText::RichText) && item.is_a?(ActionText::RichText)
302
+ @rich_text_record = item
311
303
  @parent = @rich_text_record.record
312
- @rich_text_record.save!
304
+ return head :not_found unless @parent
305
+ @rich_text_record.destroy
313
306
  @parent.touch if @parent.respond_to?(:touch)
314
307
  else
315
- @parent = @object
316
- @parent.save!
317
- end
318
- authorize!(:revert, @parent) if cancan_enabled?
319
- return unless row_html_turbo_allowed?
320
-
321
- respond_to do |format|
322
- format.turbo_stream { render_revert_turbo_streams }
308
+ @parent = item || @parent
309
+ return head :not_found unless @parent
323
310
  end
311
+ return render_revert_response if row_html_turbo_allowed?
312
+ return
313
+ end
314
+ if defined?(ActionText::RichText) && @object.is_a?(ActionText::RichText)
315
+ @rich_text_record = @object
316
+ @parent = @rich_text_record.record
317
+ return head :not_found unless @parent
318
+ @rich_text_record.save!
319
+ @parent.touch if @parent.respond_to?(:touch)
320
+ else
321
+ @parent = @object
322
+ @parent.save!
323
+ restore_rich_texts_for_reverted_parent!(@parent)
324
+ @parent.reload
324
325
  end
326
+ render_revert_response if row_html_turbo_allowed?
325
327
  end
326
328
 
327
329
  private
328
330
 
331
+ # Undoing a parent +destroy+ reifies the Apartment/Photo row only. ActionText
332
+ # bodies live in +action_text_rich_texts+ and get their own PaperTrail
333
+ # +destroy+ versions; those rows are gone after +parent.destroy+, so we also
334
+ # reify and save each matching +ActionText::RichText+ destroy snapshot.
335
+ def restore_rich_texts_for_reverted_parent!(parent)
336
+ return unless defined?(ActionText::RichText)
337
+
338
+ record_type = parent.class.base_class.name
339
+ record_id = parent.id
340
+
341
+ PaperTrail::Version.where(item_type: "ActionText::RichText", event: "destroy").find_each do |version|
342
+ attrs = version.object_deserialized
343
+ next unless attrs.is_a?(Hash)
344
+
345
+ type = attrs["record_type"] || attrs[:record_type]
346
+ rid = attrs["record_id"] || attrs[:record_id]
347
+ next unless type == record_type && rid.to_i == record_id
348
+
349
+ rich_text = version.reify
350
+ rich_text&.save!
351
+ end
352
+ end
353
+
354
+ # +revert+ is excluded from +load_and_authorize_resource+; +authorize!+ runs in the
355
+ # action. +check_authorization+ on ApplicationController still requires that flag.
356
+ def revert_authorization_subject(version)
357
+ reified = version.reify(
358
+ has_many: true,
359
+ has_and_belongs_to_many: true,
360
+ belongs_to: true
361
+ )
362
+ if defined?(ActionText::RichText) && reified.is_a?(ActionText::RichText)
363
+ return reified.record
364
+ end
365
+ return reified if reified
366
+
367
+ item = version.item
368
+ if defined?(ActionText::RichText) && item.is_a?(ActionText::RichText)
369
+ return item.record
370
+ end
371
+ return item if item
372
+
373
+ klass = version.item_type.safe_constantize
374
+ return nil unless klass && version.item_id
375
+
376
+ klass.new(id: version.item_id)
377
+ end
378
+
379
+ def render_revert_response
380
+ respond_to do |format|
381
+ format.turbo_stream { render_revert_turbo_streams }
382
+ end
383
+ end
384
+
329
385
  # Versions list lives in +<turbo-frame id="…_versions">+; POST +restore+ would otherwise
330
386
  # send +Turbo-Frame: …_versions+ while +row_close+ only returns the row frame. Stream
331
387
  # replaces both the row and the versions panel in one response.
@@ -3,7 +3,7 @@
3
3
  <div class="small-12 column">
4
4
  <%= link_to t("inline_forms.view.undo"),
5
5
  send("revert_#{@Klass.to_s.underscore}_path", @undo_version, update: @update_span),
6
- inline_forms_turbo_link_data(@update_span, method: :post).merge(class: "button") %>
6
+ inline_forms_turbo_link_data(@update_span, method: :post, turbo_stream: true).merge(class: "button") %>
7
7
  </div>
8
8
  </div>
9
9
  </turbo-frame>
@@ -1,4 +1,4 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  module InlineForms
3
- VERSION = "8.1.11"
3
+ VERSION = "8.1.15"
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inline_forms
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.1.11
4
+ version: 8.1.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ace Suares