Rails - validates_associated 两个 has_many 关系

Rails - validates_associated on two has_many relationship

我想 validate/prevent 一个不存在的 FK,然后再尝试保存模型。

class Turma < ActiveRecord::Base
    has_many :turma_professor
    has_many :professores, through: :turma_professor
    accepts_nested_attributes_for :professores
end

class TurmaProfessor < ActiveRecord::Base
    belongs_to :turma
    belongs_to :professor
end

class Professor < ActiveRecord::Base
    has_many :turma_professor
    has_many :turma, :through => :turma_professor
end

我select一个Professor,修改Professor.id并保存。 Rails 显示以下错误:

ActiveRecord::RecordNotFound (Couldn't find Professor with id=123 [WHERE "pessoas"."tipo" = 1])

有什么方法可以在 ActiveModel 的验证方法上验证这个假 ID?

您应该向 turma.rb 添加验证。

先决条件:

我猜你的控制器是这样的。

# Not raise exception because professore_ids 1, 3 exist.
Turma.new(professore_ids: [1, 3])
  Professor Load (0.9ms)  SELECT "professors".* FROM "professors" WHERE "professors"."id" IN (1, 3)
=> #<Turma id: nil, name: nil, created_at: nil, updated_at: nil>

# Raise exception because professore_id 4 doesn't exist.
Turma.new(professore_ids: [1, 4])
  Professor Load (0.9ms)  SELECT "professors".* FROM "professors" WHERE "professors"."id" IN (1, 4)
ActiveRecord::RecordNotFound: Couldn't find all Professors with 'id': (1, 4) (found 1 results, but was looking for 2)

所以你应该在你的 Turma 模型中捕捉 ActiveRecordd::RecordNotFound

如何添加验证:

class Turma < ActiveRecord::Base
  # declear not_found_professor_ids flag
  attr_reader :not_found_professor_ids

  has_many :turma_professor
  has_many :professores, through: :turma_professor, source: :professor
  accepts_nested_attributes_for :professores

  # validation
  validates :not_found_professor_ids, inclusion: { in: [true], message: "don't found" }

  def professore_ids=(ids)
    super(ids)
  rescue ActiveRecord::RecordNotFound
    # set flag
    self.not_found_professor_ids = true
  end
end

并使用它。

turma = Turma.new(professore_ids: [1,4])
turma.valid? #=> false
turma.errors.full_messages #=> ["Not found professor ids don't found"]

正好有一个 gem:https://github.com/perfectline/validates_existence

在您的连接模型上使用 validates: :turma, existence: true,一切都应该按预期工作。

您可能还想在关联的某处添加 dependent: destroy(否则您可能会得到指向已删除项目的无效关联),并且可能使用新添加的 add_foreign_key 迁移语句以保证数据库级别的链接完整性。