Я хочу проверить, что набор ассоциаций для экземпляра уникален для всех других экземпляров, и если он не уникален, я хочу, чтобы он был недействительным.
В этом случае я работаю с отношением many_to_many, поэтому у упражнения есть много элементов, а у элементов может быть много упражнений. Поэтому я бы хотел, чтобы каждое упражнение имело уникальный набор элементов, чтобы в упражнении было как можно больше ассоциаций элементов, но никогда не было бы такой же комбинации элементов, как в другом упражнении.
Я попытался добавить пользовательскую проверку в модель объединения, но это не работает, когда я отправляю много пересмотренных ассоциаций одновременно (например, когда я редактирую ассоциации через вложенную форму)
Я также пытался поместить валидацию в модель упражнения, сравнивая ассоциации созданного или обновленного упражнения со всеми другими существующими наборами ассоциаций элементов упражнения, но, похоже, это не работает, потому что ассоциации не созданы до тех пор, пока мне не нужно проверить их. Так что, кажется, мне нужны построенные ассоциации, чтобы подтвердить их уникальность, но как только они будут созданы, уже слишком поздно.
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