Disallow self- and descendant-reference for base/parent

This commit is contained in:
2025-01-12 19:15:43 +01:00
parent 17b4e4f8a7
commit 0652d4a89b
3 changed files with 23 additions and 0 deletions

View File

@@ -8,6 +8,10 @@ class Quantity < ApplicationRecord
validate if: ->{ parent.present? } do
errors.add(:parent, :user_mismatch) unless user == parent.user
errors.add(:parent, :self_reference) if self == parent
end
validate if: ->{ parent.present? }, on: :update do
errors.add(:parent, :descendant_reference) if ancestor_of?(parent)
end
validates :name, presence: true, uniqueness: {scope: [:user_id, :parent_id]},
length: {maximum: type_for_attribute(:name).limit}
@@ -99,4 +103,15 @@ class Quantity < ApplicationRecord
end
end
end
def ancestor_of?(descendant)
quantities = Quantity.arel_table
ancestors = Arel::Table.new('ancestors')
Quantity.with_recursive(ancestors: [
user.quantities.where(id: descendant.id),
user.quantities.joins(quantities.create_join(
ancestors, quantities.create_on(quantities[:id].eq(ancestors[:parent_id]))
))
]).from(ancestors).exists?(ancestors: {id: id})
end
end

View File

@@ -7,6 +7,7 @@ class Unit < ApplicationRecord
validate if: ->{ base.present? } do
errors.add(:base, :user_mismatch) unless user == base.user
errors.add(:base, :self_reference) if self == base
errors.add(:base, :multilevel_nesting) if base.base.present?
end
validates :symbol, presence: true, uniqueness: {scope: :user_id},