summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorerdgeist <erdgeist@erdgeist.org>2026-07-30 16:50:19 +0200
committererdgeist <erdgeist@erdgeist.org>2026-07-30 16:50:19 +0200
commit37c542bee952193ebfbced8529b8699e2712fdc8 (patch)
treedf8d70c586002a08b85ba1143a93f9444215ff63 /app
parent970f0daaa7097d1a34cf3daa6266b80b93c190a9 (diff)
Localise model validation messages and refusal reasons
Diffstat (limited to 'app')
-rw-r--r--app/models/node.rb42
-rw-r--r--app/models/related_asset.rb2
2 files changed, 27 insertions, 17 deletions
diff --git a/app/models/node.rb b/app/models/node.rb
index 1e61f9fe..602382fb 100644
--- a/app/models/node.rb
+++ b/app/models/node.rb
@@ -236,7 +236,8 @@ class Node < ApplicationRecord
236 return nil unless self.draft || staged_slug || staged_parent_id 236 return nil unless self.draft || staged_slug || staged_parent_id
237 237
238 if in_trash? || trash_node? 238 if in_trash? || trash_node?
239 raise ActiveRecord::RecordInvalid.new(self), "Cannot publish a node in the Trash" 239 errors.add(:base, :publish_in_trash)
240 raise ActiveRecord::RecordInvalid.new(self)
240 end 241 end
241 242
242 path_before = self.unique_name 243 path_before = self.unique_name
@@ -265,7 +266,8 @@ class Node < ApplicationRecord
265 new_parent = Node.find(staged_parent_id) 266 new_parent = Node.find(staged_parent_id)
266 267
267 if new_parent == self || self.descendants.include?(new_parent) 268 if new_parent == self || self.descendants.include?(new_parent)
268 raise ActiveRecord::RecordInvalid.new(self), "Cannot move a node under itself or one of its own descendants" 269 errors.add(:base, :move_under_self)
270 raise ActiveRecord::RecordInvalid.new(self)
269 end 271 end
270 272
271 self.staged_parent_id = nil 273 self.staged_parent_id = nil
@@ -316,7 +318,10 @@ class Node < ApplicationRecord
316 # at the root, carrying the leaving-public-view snapshot. 318 # at the root, carrying the leaving-public-view snapshot.
317 def trash! current_user = nil 319 def trash! current_user = nil
318 return nil if in_trash? 320 return nil if in_trash?
319 raise ActiveRecord::RecordInvalid.new(self), "The Trash node itself cannot be trashed" if trash_node? 321 if trash_node?
322 errors.add(:base, :trash_the_trash)
323 raise ActiveRecord::RecordInvalid.new(self)
324 end
320 325
321 ActiveRecord::Base.transaction do 326 ActiveRecord::Base.transaction do
322 path_before = unique_name 327 path_before = unique_name
@@ -360,7 +365,8 @@ class Node < ApplicationRecord
360 365
361 if new_parent.nil? || new_parent == self || descendants.include?(new_parent) || 366 if new_parent.nil? || new_parent == self || descendants.include?(new_parent) ||
362 new_parent.trash_node? || new_parent.in_trash? 367 new_parent.trash_node? || new_parent.in_trash?
363 raise ActiveRecord::RecordInvalid.new(self), "Restore target must be a living node" 368 errors.add(:base, :restore_target_invalid)
369 raise ActiveRecord::RecordInvalid.new(self)
364 end 370 end
365 371
366 ActiveRecord::Base.transaction do 372 ActiveRecord::Base.transaction do
@@ -376,7 +382,7 @@ class Node < ApplicationRecord
376 end 382 end
377 end 383 end
378 384
379 # Final deletion -- only from inside the Trash. Removes the whole 385 # Final deletion, only from inside the Trash. Removes the whole
380 # subtree, deepest first, each node through a real destroy! so every 386 # subtree, deepest first, each node through a real destroy! so every
381 # per-node cascade runs (the categorical difference from the old 387 # per-node cascade runs (the categorical difference from the old
382 # delete_all nuke). refuse_destroy_with_children on bare destroy is 388 # delete_all nuke). refuse_destroy_with_children on bare destroy is
@@ -384,7 +390,10 @@ class Node < ApplicationRecord
384 # One log entry at the root, per the subtree rule, written before the 390 # One log entry at the root, per the subtree rule, written before the
385 # rows die. 391 # rows die.
386 def destroy_from_trash! current_user = nil 392 def destroy_from_trash! current_user = nil
387 raise ActiveRecord::RecordInvalid.new(self), "Nodes are only destroyed from the Trash" unless in_trash? 393 unless in_trash?
394 errors.add(:base, :destroy_outside_trash)
395 raise ActiveRecord::RecordInvalid.new(self)
396 end
388 397
389 ActiveRecord::Base.transaction do 398 ActiveRecord::Base.transaction do
390 doomed = self_and_descendants_ordered_with_level 399 doomed = self_and_descendants_ordered_with_level
@@ -476,7 +485,8 @@ class Node < ApplicationRecord
476 # :headline => nil | :set | :kept_existing | :not_eligible } 485 # :headline => nil | :set | :kept_existing | :not_eligible }
477 def attach_asset! asset, user:, headline: false 486 def attach_asset! asset, user:, headline: false
478 if in_trash? || trash_node? 487 if in_trash? || trash_node?
479 raise ActiveRecord::RecordInvalid.new(self), "Cannot attach assets to a node in the Trash" 488 errors.add(:base, :attach_in_trash)
489 raise ActiveRecord::RecordInvalid.new(self)
480 end 490 end
481 491
482 if lock_owner && lock_owner != user 492 if lock_owner && lock_owner != user
@@ -610,7 +620,7 @@ class Node < ApplicationRecord
610 # The Trash feature will be the ordinary path to deletion. 620 # The Trash feature will be the ordinary path to deletion.
611 def refuse_destroy_with_children 621 def refuse_destroy_with_children
612 return unless children.exists? 622 return unless children.exists?
613 errors.add(:base, "Cannot destroy a node that still has children") 623 errors.add(:base, :has_children)
614 throw :abort 624 throw :abort
615 end 625 end
616 626
@@ -668,15 +678,15 @@ class Node < ApplicationRecord
668 678
669 def reserved_slug_stays_reserved 679 def reserved_slug_stays_reserved
670 if parent&.root? && !trash_node_already_me? 680 if parent&.root? && !trash_node_already_me?
671 errors.add(:slug, "is reserved for the Trash") if slug == CccConventions::TRASH_SLUG 681 errors.add(:slug, :reserved_for_trash) if slug == CccConventions::TRASH_SLUG
672 errors.add(:staged_slug, "is reserved for the Trash") if staged_slug == CccConventions::TRASH_SLUG 682 errors.add(:staged_slug, :reserved_for_trash) if staged_slug == CccConventions::TRASH_SLUG
673 end 683 end
674 684
675 if persisted? && slug_was == CccConventions::TRASH_SLUG && Node.find(id).trash_node? 685 if persisted? && slug_was == CccConventions::TRASH_SLUG && Node.find(id).trash_node?
676 errors.add(:slug, "of the Trash node cannot change") if slug_changed? 686 errors.add(:slug, :trash_immutable) if slug_changed?
677 errors.add(:parent_id, "of the Trash node cannot change") if parent_id_changed? 687 errors.add(:parent_id, :trash_immutable) if parent_id_changed?
678 errors.add(:staged_slug, "must stay empty on the Trash node") if staged_slug.present? 688 errors.add(:staged_slug, :trash_must_be_empty) if staged_slug.present?
679 errors.add(:staged_parent_id, "must stay empty on the Trash node") if staged_parent_id.present? 689 errors.add(:staged_parent_id, :trash_must_be_empty) if staged_parent_id.present?
680 end 690 end
681 end 691 end
682 692
@@ -687,12 +697,12 @@ class Node < ApplicationRecord
687 697
688 def no_head_inside_trash 698 def no_head_inside_trash
689 return unless head_id.present? 699 return unless head_id.present?
690 errors.add(:head_id, "cannot exist inside the Trash") if in_trash? || trash_node? 700 errors.add(:head_id, :inside_trash) if in_trash? || trash_node?
691 end 701 end
692 702
693 def refuse_destroying_trash_node 703 def refuse_destroying_trash_node
694 return unless trash_node? 704 return unless trash_node?
695 errors.add(:base, "The Trash node cannot be destroyed") 705 errors.add(:base, :trash_undeletable)
696 throw :abort 706 throw :abort
697 end 707 end
698end 708end
diff --git a/app/models/related_asset.rb b/app/models/related_asset.rb
index 8f8d49cb..caf8afda 100644
--- a/app/models/related_asset.rb
+++ b/app/models/related_asset.rb
@@ -12,6 +12,6 @@ class RelatedAsset < ApplicationRecord
12 12
13 def headline_only_for_images 13 def headline_only_for_images
14 return unless asset 14 return unless asset
15 errors.add(:headline, "can only be set on image or PDF assets") if headline? && !(asset.image? || asset.pdf?) 15 errors.add(:headline, :images_and_pdfs_only) if headline? && !(asset.image? || asset.pdf?)
16 end 16 end
17end 17end