diff options
Diffstat (limited to 'app/models/node.rb')
| -rw-r--r-- | app/models/node.rb | 51 |
1 files changed, 22 insertions, 29 deletions
diff --git a/app/models/node.rb b/app/models/node.rb index 4b7c9772..5c28a786 100644 --- a/app/models/node.rb +++ b/app/models/node.rb | |||
| @@ -128,6 +128,7 @@ class Node < ApplicationRecord | |||
| 128 | 128 | ||
| 129 | def autosave! attributes, current_user | 129 | def autosave! attributes, current_user |
| 130 | ensure_autosave!(current_user) | 130 | ensure_autosave!(current_user) |
| 131 | attributes = attributes.except(:slug, "slug") if attributes[:slug].blank? && attributes["slug"].blank? | ||
| 131 | self.autosave.assign_attributes(attributes) | 132 | self.autosave.assign_attributes(attributes) |
| 132 | self.autosave.save! | 133 | self.autosave.save! |
| 133 | self.autosave | 134 | self.autosave |
| @@ -227,17 +228,9 @@ class Node < ApplicationRecord | |||
| 227 | self.reload | 228 | self.reload |
| 228 | end | 229 | end |
| 229 | 230 | ||
| 230 | def staged_slug=(value) | ||
| 231 | if head.blank? | ||
| 232 | self.slug = value | ||
| 233 | else | ||
| 234 | super | ||
| 235 | end | ||
| 236 | end | ||
| 237 | |||
| 238 | def publish_draft! current_user = nil | 231 | def publish_draft! current_user = nil |
| 239 | # Return nil if nothing to publish and no staged changes | 232 | # Return nil if nothing to publish |
| 240 | return nil unless self.draft || staged_slug || staged_parent_id | 233 | return nil unless self.draft |
| 241 | 234 | ||
| 242 | guard_live_change!(current_user, :target_path => prospective_unique_name) | 235 | guard_live_change!(current_user, :target_path => prospective_unique_name) |
| 243 | 236 | ||
| @@ -263,26 +256,28 @@ class Node < ApplicationRecord | |||
| 263 | **NodeAction.head_diff(outgoing_head, self.head)) | 256 | **NodeAction.head_diff(outgoing_head, self.head)) |
| 264 | end | 257 | end |
| 265 | 258 | ||
| 266 | if staged_slug && (staged_slug != slug) | 259 | if self.head.slug.present? && self.head.slug != slug |
| 267 | self.slug = staged_slug | 260 | self.slug = self.head.slug |
| 268 | self.staged_slug = nil | ||
| 269 | end | 261 | end |
| 270 | 262 | ||
| 271 | if staged_parent_id && (staged_parent_id != parent_id) | 263 | if self.head.parent_node_id && self.head.parent_node_id != parent_id |
| 272 | new_parent = Node.find(staged_parent_id) | 264 | new_parent = Node.find_by(:id => self.head.parent_node_id) |
| 273 | 265 | ||
| 274 | if new_parent == self || self.descendants.include?(new_parent) | 266 | unless new_parent |
| 267 | errors.add(:base, :move_target_missing) | ||
| 268 | raise ActiveRecord::RecordInvalid.new(self) | ||
| 269 | end | ||
| 270 | |||
| 271 | if new_parent == self || self.descendants.include?(new_parent) || | ||
| 272 | new_parent.trash_node? || new_parent.in_trash? | ||
| 275 | errors.add(:base, :move_under_self) | 273 | errors.add(:base, :move_under_self) |
| 276 | raise ActiveRecord::RecordInvalid.new(self) | 274 | raise ActiveRecord::RecordInvalid.new(self) |
| 277 | end | 275 | end |
| 278 | 276 | ||
| 279 | self.staged_parent_id = nil | ||
| 280 | self.save! | 277 | self.save! |
| 281 | self.move_to_child_of(new_parent) | 278 | self.move_to_child_of(new_parent) |
| 282 | else | 279 | else |
| 283 | unless self.save | 280 | raise ActiveRecord::RecordInvalid.new(self) unless self.save |
| 284 | raise ActiveRecord::RecordInvalid.new(self) | ||
| 285 | end | ||
| 286 | end | 281 | end |
| 287 | 282 | ||
| 288 | self.reload | 283 | self.reload |
| @@ -369,9 +364,12 @@ class Node < ApplicationRecord | |||
| 369 | # subtree comes back exactly as it sits in the Trash: all drafts, | 364 | # subtree comes back exactly as it sits in the Trash: all drafts, |
| 370 | # nothing published. Republication is a separate, witnessed act | 365 | # nothing published. Republication is a separate, witnessed act |
| 371 | # per node. | 366 | # per node. |
| 372 | def restore_from_trash! new_parent, current_user = nil | 367 | def restore_from_trash! current_user = nil |
| 373 | return nil unless in_trash? | 368 | return nil unless in_trash? |
| 374 | 369 | ||
| 370 | target = (draft || head)&.parent_node_id | ||
| 371 | new_parent = target ? Node.find_by(:id => target) : nil | ||
| 372 | |||
| 375 | if new_parent.nil? || new_parent == self || descendants.include?(new_parent) || | 373 | if new_parent.nil? || new_parent == self || descendants.include?(new_parent) || |
| 376 | new_parent.trash_node? || new_parent.in_trash? | 374 | new_parent.trash_node? || new_parent.in_trash? |
| 377 | errors.add(:base, :restore_target_invalid) | 375 | errors.add(:base, :restore_target_invalid) |
| @@ -593,11 +591,9 @@ class Node < ApplicationRecord | |||
| 593 | root? || self.class.restricted_path?(unique_name) | 591 | root? || self.class.restricted_path?(unique_name) |
| 594 | end | 592 | end |
| 595 | 593 | ||
| 594 | # Falls back to the live address when the draft records none. | ||
| 596 | def prospective_unique_name | 595 | def prospective_unique_name |
| 597 | target_parent = staged_parent_id ? Node.find_by(:id => staged_parent_id) : parent | 596 | (draft || head)&.prospective_unique_name || unique_name |
| 598 | return nil unless target_parent | ||
| 599 | |||
| 600 | [target_parent.unique_name.presence, staged_slug.presence || slug].compact.join("/") | ||
| 601 | end | 597 | end |
| 602 | 598 | ||
| 603 | # Returns immutable node id for all new nodes so that the atom feed entry ids | 599 | # Returns immutable node id for all new nodes so that the atom feed entry ids |
| @@ -702,7 +698,7 @@ class Node < ApplicationRecord | |||
| 702 | # that draft and publishes it. | 698 | # that draft and publishes it. |
| 703 | def initialize_empty_page | 699 | def initialize_empty_page |
| 704 | if self.pages.empty? | 700 | if self.pages.empty? |
| 705 | self.draft = self.pages.create! | 701 | self.draft = self.pages.create!(:slug => self.slug, :parent_node_id => self.parent_id) |
| 706 | self.save | 702 | self.save |
| 707 | end | 703 | end |
| 708 | end | 704 | end |
| @@ -744,14 +740,11 @@ class Node < ApplicationRecord | |||
| 744 | def reserved_slug_stays_reserved | 740 | def reserved_slug_stays_reserved |
| 745 | if parent&.root? && !trash_node_already_me? | 741 | if parent&.root? && !trash_node_already_me? |
| 746 | errors.add(:slug, :reserved_for_trash) if slug == CccConventions::TRASH_SLUG | 742 | errors.add(:slug, :reserved_for_trash) if slug == CccConventions::TRASH_SLUG |
| 747 | errors.add(:staged_slug, :reserved_for_trash) if staged_slug == CccConventions::TRASH_SLUG | ||
| 748 | end | 743 | end |
| 749 | 744 | ||
| 750 | if persisted? && slug_was == CccConventions::TRASH_SLUG && Node.find(id).trash_node? | 745 | if persisted? && slug_was == CccConventions::TRASH_SLUG && Node.find(id).trash_node? |
| 751 | errors.add(:slug, :trash_immutable) if slug_changed? | 746 | errors.add(:slug, :trash_immutable) if slug_changed? |
| 752 | errors.add(:parent_id, :trash_immutable) if parent_id_changed? | 747 | errors.add(:parent_id, :trash_immutable) if parent_id_changed? |
| 753 | errors.add(:staged_slug, :trash_must_be_empty) if staged_slug.present? | ||
| 754 | errors.add(:staged_parent_id, :trash_must_be_empty) if staged_parent_id.present? | ||
| 755 | end | 748 | end |
| 756 | end | 749 | end |
| 757 | 750 | ||
