inline_forms 8.1.11 → 8.1.13

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: 5ae9fa81e904412a8066f7b989cc62d751ecd2ec388e86280a9f29c40c71066c
4
+ data.tar.gz: a1ef139cf1a6ab1827a79dfe4b13b83cc106dbaf4618f3840a4f00c623139d30
5
5
  SHA512:
6
- metadata.gz: 37d86c5be4e09df199b6d23b8ee91c2488bb98b178b352213dce075234152cc9ef03d119cd2ccd0eb41632d4e6ec5724918d6f2cfdbd70889ed5a0e4b7a959d1
7
- data.tar.gz: 3b40a5c9b0de4707715d43d2186f3d1e4570b7c0cfa17f55f6aa7aa2c151b325bf91a670897ebc3379a1ba086081953f4a0d2f3806a3cd83a13c4fd6149443bb
6
+ metadata.gz: 87a7b60dbc16267a2b1415374747785df190d82fb00d9df751dd6b3c47e9f02a82e2d2127ff04784fe659d6709ffd64044952c013c11fc49af0bad47284a29c7
7
+ data.tar.gz: 4452500f6fa5b2e6f1010a61e3a5f30ba755b44de4861a09868787136a4f06aa4873d545b03e68af782d0239bd8d55289c60cbdce22fde565d26d4ccda24a28f
data/CHANGELOG.md CHANGED
@@ -4,6 +4,26 @@ All notable changes to this project are documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [8.1.13] - 2026-05-28
8
+
9
+ ### Fixed
10
+
11
+ - **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.
12
+
13
+ ### Added
14
+
15
+ - **Regression test** on `FormElementShowcase` "Empty demo": edit `body_plain_area`, delete, undo, assert text and undo URL use the destroy version.
16
+
17
+ ## [8.1.12] - 2026-05-28
18
+
19
+ ### Fixed
20
+
21
+ - **`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.
22
+
23
+ ### Added
24
+
25
+ - **Regression test** `example_app_showcase_row_turbo_test.rb`: destroy + undo revert on `FormElementShowcase`.
26
+
7
27
  ## [8.1.11] - 2026-05-28
8
28
 
9
29
  ### 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,91 @@ 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!
324
323
  end
324
+ render_revert_response if row_html_turbo_allowed?
325
325
  end
326
326
 
327
327
  private
328
328
 
329
+ # +revert+ is excluded from +load_and_authorize_resource+; +authorize!+ runs in the
330
+ # action. +check_authorization+ on ApplicationController still requires that flag.
331
+ def revert_authorization_subject(version)
332
+ reified = version.reify(
333
+ has_many: true,
334
+ has_and_belongs_to_many: true,
335
+ belongs_to: true
336
+ )
337
+ if defined?(ActionText::RichText) && reified.is_a?(ActionText::RichText)
338
+ return reified.record
339
+ end
340
+ return reified if reified
341
+
342
+ item = version.item
343
+ if defined?(ActionText::RichText) && item.is_a?(ActionText::RichText)
344
+ return item.record
345
+ end
346
+ return item if item
347
+
348
+ klass = version.item_type.safe_constantize
349
+ return nil unless klass && version.item_id
350
+
351
+ klass.new(id: version.item_id)
352
+ end
353
+
354
+ def render_revert_response
355
+ respond_to do |format|
356
+ format.turbo_stream { render_revert_turbo_streams }
357
+ end
358
+ end
359
+
329
360
  # Versions list lives in +<turbo-frame id="…_versions">+; POST +restore+ would otherwise
330
361
  # send +Turbo-Frame: …_versions+ while +row_close+ only returns the row frame. Stream
331
362
  # 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.13"
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.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ace Suares