summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorerdgeist <erdgeist@erdgeist.org>2026-07-23 19:45:47 +0200
committererdgeist <erdgeist@erdgeist.org>2026-07-23 19:45:47 +0200
commitaedf5778aba87c4e8d036dde2a0b6ec79cf8b342 (patch)
tree059a8954c332d0a7c3e48e44906a4104d4338007 /app
parentf993853db3e233f05a55de5ba2a87b77acf041aa (diff)
Keep in-editor asset curation off the head, layering it like every edit
ensure_autosave! gives body keystrokes and asset curation one shared layer, so head is never mutated in place and every curation change surfaces in the publish delta. Stale rendered join ids are mapped across the clone via asset_id. Curation now requires holding the lock; a missing lock answers 423, matching the autosave endpoint.
Diffstat (limited to 'app')
-rw-r--r--app/controllers/related_assets_controller.rb18
-rw-r--r--app/models/node.rb12
2 files changed, 19 insertions, 11 deletions
diff --git a/app/controllers/related_assets_controller.rb b/app/controllers/related_assets_controller.rb
index ca894f2f..3aa6d3db 100644
--- a/app/controllers/related_assets_controller.rb
+++ b/app/controllers/related_assets_controller.rb
@@ -2,6 +2,10 @@ class RelatedAssetsController < ApplicationController
2 before_action :login_required 2 before_action :login_required
3 before_action :find_node 3 before_action :find_node
4 4
5 rescue_from LockedByAnotherUser do
6 head :locked
7 end
8
5 def search 9 def search
6 term = params[:search_term].to_s.strip 10 term = params[:search_term].to_s.strip
7 attached_ids = @node.editable_page.related_assets.pluck(:asset_id) 11 attached_ids = @node.editable_page.related_assets.pluck(:asset_id)
@@ -19,8 +23,9 @@ class RelatedAssetsController < ApplicationController
19 end 23 end
20 24
21 def create 25 def create
26 page = @node.ensure_autosave!(current_user)
22 asset = Asset.find(params[:asset_id]) 27 asset = Asset.find(params[:asset_id])
23 related = @node.editable_page.related_assets.find_or_create_by!(asset: asset) 28 related = page.related_assets.find_or_create_by!(asset: asset)
24 29
25 render json: { 30 render json: {
26 id: related.id, 31 id: related.id,
@@ -35,22 +40,25 @@ class RelatedAssetsController < ApplicationController
35 end 40 end
36 41
37 def destroy 42 def destroy
38 @node.editable_page.related_assets.find(params[:id]).destroy 43 page = @node.ensure_autosave!(current_user)
44 source = RelatedAsset.find(params[:id])
45 page.related_assets.find_by!(:asset_id => source.asset_id).destroy
39 head :ok 46 head :ok
40 end 47 end
41 48
42 def update 49 def update
43 related = @node.editable_page.related_assets.find(params[:id]) 50 page = @node.ensure_autosave!(current_user)
51 source = RelatedAsset.find(params[:id])
52 related = page.related_assets.find_by!(:asset_id => source.asset_id)
44 53
45 if params.key?(:headline) 54 if params.key?(:headline)
46 RelatedAsset.transaction do 55 RelatedAsset.transaction do
47 @node.editable_page.related_assets.update_all(headline: false) 56 page.related_assets.update_all(headline: false)
48 related.update!(headline: true) if params[:headline] == "true" 57 related.update!(headline: true) if params[:headline] == "true"
49 end 58 end
50 else 59 else
51 related.insert_at(params[:position].to_i) 60 related.insert_at(params[:position].to_i)
52 end 61 end
53
54 head :ok 62 head :ok
55 end 63 end
56 64
diff --git a/app/models/node.rb b/app/models/node.rb
index 274b2f94..02502f6c 100644
--- a/app/models/node.rb
+++ b/app/models/node.rb
@@ -112,18 +112,18 @@ class Node < ApplicationRecord
112 end 112 end
113 end 113 end
114 114
115 # Creates or updates the autosave buffer from the given attributes. 115 def ensure_autosave! current_user
116 # Autosave rows are never associated to the node via node_id -- they
117 # must never appear in self.pages / the revisions list, which is the
118 # whole reason autosave exists as a separate, unversioned layer.
119 def autosave! attributes, current_user
120 assert_locked_by! current_user 116 assert_locked_by! current_user
121
122 unless self.autosave 117 unless self.autosave
123 self.autosave = Page.create!(:editor => current_user) 118 self.autosave = Page.create!(:editor => current_user)
124 self.autosave.clone_attributes_from(self.draft || self.head) if self.draft || self.head 119 self.autosave.clone_attributes_from(self.draft || self.head) if self.draft || self.head
125 self.save! 120 self.save!
126 end 121 end
122 self.autosave
123 end
124
125 def autosave! attributes, current_user
126 ensure_autosave!(current_user)
127 self.autosave.assign_attributes(attributes) 127 self.autosave.assign_attributes(attributes)
128 self.autosave.save! 128 self.autosave.save!
129 self.autosave 129 self.autosave