Rails - 在两个has_many关系上的validates_associated

时间:2015-01-28 01:04:52

标签: ruby-on-rails ruby-on-rails-4

我想在尝试保存模型之前验证/阻止不存在的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

我选择Professor,更改Professor.id并保存。 Rails向我显示以下错误:

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

有一些方法可以在ActiveModel的验证方法上验证这个假身份证吗?

2 个答案:

答案 0 :(得分:1)

您应该将验证添加到 turma.rb

<强> PREFEQUISITE:

我想你的控制器就像下面一样。

# 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)

因此,您应该在ActiveRecordd::RecordNotFound模型中抓住Turma

如何添加验证:

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"]

答案 1 :(得分:0)

确切地说有一个宝石:https://github.com/perfectline/validates_existence

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

您可能还想将dependent: destroy添加到您的关联中(或者您最终会指向指向已删除项目的无效关联),并且可能使用新添加的add_foreign_key迁移语句来保证数据库级别的链接完整性。