From 65da515e27939c90a66ec3b063b5e58943d3dcea Mon Sep 17 00:00:00 2001 From: erdgeist Date: Tue, 21 Jul 2026 17:34:13 +0200 Subject: Resolve preview's page-to-node lookup for every layer pages_controller#preview loaded a page by id and rendered it directly, assuming @page.node was always present. True for head and draft, since both carry a real node_id: false for autosave, which deliberately has node_id: nil (the mechanism that excludes it from Node#pages and the revision count). A node with an autosave and no draft underneath it: lock, start editing, never explicitly save a draft: loads that autosave directly with no node at all, and any view code assuming @page.node is real (headline image, credits, gallery links) raises. When @page has no node, resolve it by checking autosave_id, then draft_id, then head_id on Node, and set @page.node in memory only: the autosave's node_id: nil is never persisted differently. The existing swap from draft to a fresher autosave, when both exist, is unchanged. Three tests: draft with a fresher autosave on top, autosave with no draft underneath, and the ordinary head-only case with neither. --- app/controllers/pages_controller.rb | 13 ++++++ test/controllers/pages_controller_test.rb | 69 ++++++++++++++++++++++++++++++- 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb index 0b7e98f..326fbd4 100644 --- a/app/controllers/pages_controller.rb +++ b/app/controllers/pages_controller.rb @@ -6,6 +6,19 @@ class PagesController < ApplicationController def preview @page = Page.find(params[:id]) + unless @page.node + node = Node.find_by(autosave_id: @page.id) || + Node.find_by(draft_id: @page.id) || + Node.find_by(head_id: @page.id) + @page.node = node if node + end + + node ||= @page.node + if node && node.draft_id == @page.id && node.autosave + @page = node.autosave + @page.node = node + end + if @page template = @page.valid_template diff --git a/test/controllers/pages_controller_test.rb b/test/controllers/pages_controller_test.rb index 3879014..732869b 100644 --- a/test/controllers/pages_controller_test.rb +++ b/test/controllers/pages_controller_test.rb @@ -1,5 +1,72 @@ require 'test_helper' class PagesControllerTest < ActionController::TestCase - # will be removed anyway + test "preview shows the autosave when a draft and an autosave both exist" do + login_as :quentin + + node = Node.root.children.create!(:slug => "preview_retest") + node.draft.update!(:title => "draft title") + node.publish_draft! + + node.draft + node.lock_for_editing!(users(:quentin)) + node.autosave!({ :title => "draft title" }, users(:quentin)) + node.save_draft!(users(:quentin)) + node.autosave!({ :title => "autosave title" }, users(:quentin)) + + get :preview, params: { :id => node.draft_id } + + assert_response :success + assert_match "autosave title", response.body + end + + test "preview renders a headlined image on the autosave without crashing" do + login_as :quentin + + node = Node.root.children.create!(:slug => "preview_retest_with_image") + node.lock_for_editing!(users(:quentin)) + node.autosave!({ :title => "draft title" }, users(:quentin)) + node.save_draft!(users(:quentin)) + node.autosave!({ :title => "autosave title" }, users(:quentin)) + + asset = Asset.create!(:name => "test", :upload_content_type => "image/png") + node.autosave.related_assets.create!(:asset_id => asset.id, :position => 1, :headline => true) + + get :preview, params: { :id => node.draft_id } + + assert_response :success + assert_match "autosave title", response.body + end + + test "preview shows the autosave when no draft exists at all" do + login_as :quentin + + node = Node.root.children.create!(:slug => "preview_retest_no_draft") + node.draft.destroy + node.update_column(:draft_id, nil) + + node.lock_for_editing!(users(:quentin)) + node.autosave!({ :title => "autosave only title" }, users(:quentin)) + + asset = Asset.create!(:name => "test", :upload_content_type => "image/png") + node.autosave.related_assets.create!(:asset_id => asset.id, :position => 1) + + get :preview, params: { :id => node.autosave_id } + + assert_response :success + assert_match "autosave only title", response.body + end + + test "preview shows head normally when there is no draft or autosave" do + login_as :quentin + + node = Node.root.children.create!(:slug => "preview_retest_head_only") + node.draft.update!(:title => "head title") + node.publish_draft! + + get :preview, params: { :id => node.head_id } + + assert_response :success + assert_match "head title", response.body + end end -- cgit v1.3