diff --git a/app/models/spina/page.rb b/app/models/spina/page.rb index 0c484748a..b28ab87c7 100644 --- a/app/models/spina/page.rb +++ b/app/models/spina/page.rb @@ -85,6 +85,7 @@ def next_sibling end def set_materialized_path + freeze_url_title self.old_path = materialized_path self.materialized_path = localized_materialized_path @@ -118,6 +119,17 @@ def rewrite_rule RewriteRule.where(old_path: old_path).first_or_create.update(new_path: materialized_path) if old_path != materialized_path end + # Locks the slug of a live page by writing it to url_title, so changing + # the title no longer changes the URL. The URL can still be changed + # explicitly through url_title. + def freeze_url_title + return unless persisted? && live? + return if homepage? || url_title(default: nil).present? + + current_slug = materialized_path.to_s.split("/").last + self.url_title = current_slug if current_slug.present? + end + def localized_materialized_path segments = if Mobility.locale == I18n.default_locale [Spina.mounted_at, generate_materialized_path] diff --git a/test/models/spina/page_test.rb b/test/models/spina/page_test.rb index 6d6f29841..9cd842650 100644 --- a/test/models/spina/page_test.rb +++ b/test/models/spina/page_test.rb @@ -40,6 +40,29 @@ def setup assert_equal "/custom-slug", @demo.materialized_path end + test "changing the title of a live page keeps the url" do + page = FactoryBot.create(:page, title: "First title") + page.update(title: "Second title") + + assert_equal "/first-title", page.materialized_path + assert_empty RewriteRule.all + end + + test "changing url_title still changes the url" do + page = FactoryBot.create(:page, title: "First title") + page.update(url_title: "different-url") + + assert_equal "/different-url", page.materialized_path + assert_equal [["/first-title", "/different-url"]], RewriteRule.pluck(:old_path, :new_path) + end + + test "drafts keep following the title" do + page = FactoryBot.create(:page, title: "First title", draft: true) + page.update(title: "Second title") + + assert_equal "/second-title", page.materialized_path + end + test "build slug from ancestors" do about = FactoryBot.create :about_page page = FactoryBot.create :services_page