我想验证一个实例的关联集对所有其他实例都是唯一的,如果不是唯一的,我希望它无效。
在这种情况下,我使用的是many_to_many关系,因此,一个Exercise有许多元素,而元素可以有许多Exercises。因此,我希望每个练习都具有一组独特的元素,以便一个练习可以具有尽可能多的元素关联,但永远不要与另一个练习具有相同的元素组合。
我尝试将自定义验证添加到联接模型中,但是当我一次提交很多修订的关联时(例如,当我通过嵌套表单编辑关联时),这是行不通的
我还尝试通过将已创建或更新的练习的关联与所有其他存在的练习元素关联集进行比较来将验证放入“练习”模型中,但这似乎不起作用,因为未创建关联直到我需要验证它们。因此,似乎需要建立关联才能验证其唯一性,但是一旦建立关联,就为时已晚。
class Exercise < ApplicationRecord
has_many :exercise_elements, dependent: :destroy
has_many :elements, through: :exercise_elements
accepts_nested_attributes_for :exercise_elements, allow_destroy: true
validate :element_uniqueness, if: :elements_unique?, on: :update
def elements_unique?
all_exercises_but_self = Exercise.where.not(id: self.id)
all_exercises = all_exercises_but_self.map(&:elements)
all_sorted = all_exercises.each.sort
this_exercise = self.elements.sort
all_sorted.include?(this_exercise) ? true : false
end
def element_uniqueness
if elements_unique?
self.errors[:base] << "Exercise already exists, consider adding
different elements"
end
end
end
class ExerciseElement < ApplicationRecord
belongs_to :exercise
belongs_to :element
end
class Element < ApplicationRecord
belongs_to :element_category
has_many :exercise_elements
has_many :exercises, through: :exercise_elements
end
我希望
exercise1 = Exercise.create
exercise1.elements.push([Element.find(1), Element.find(2)])
exercise1.valid? > true
exercise2 = Exercise.create
exercise2.elements << Element.find(2)
exercise2.valid? > true
exercise2.elements << Element.find(1)
exercise2.valid? > false # invalid because associated elements are not a
# unique set
# because exercise2.elements == exercise1.elements