如何验证一组独特的多对多关联?

时间:2019-01-02 04:19:38

标签: ruby-on-rails validation many-to-many associations

我想验证一个实例的关联集对所有其他实例都是唯一的,如果不是唯一的,我希望它无效。

在这种情况下,我使用的是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

0 个答案:

没有答案