我有一个Company
模型和一个Employer
模型。Employer
belongs_to :company
和Company
has_many :employers
。在我的Employer
模型中,我有以下验证:
validates :company_id, inclusion: {in: Company.pluck(:id).prepend(nil)}
我遇到了一个问题,上面的验证失败。下面是一个控制器操作中的示例设置,它将导致验证失败:
company = Company.new(company_params)
# company_params contains nested attributes for employers
company.employers.each do |employer|
employer.password = SecureRandom.hex
end
company.employers.first.role = 'Admin' if client.employers.count == 1
company.save!
admin = company.employers.where(role: 'Admin').order(created_at: :asc).last
admin.update(some_attr: 'some_val')
在示例代码片段的最后一行,admin.update
将失败,因为验证正在检查company_id
是否包含在列表中,实际上并不包含,因为列表是在company
保存之前生成的。
显然,有一些方法可以解决这个问题,比如获取company.id
的值,然后用它来定义admin
,但这似乎是一个迂回的解决方案。我想知道的是,是否有更好的方法来解决这个问题。
更新
显然我建议的可能的变通方法根本不起作用。
new_company = Company.find(company.id)
admin = new_company.employers.where(role: 'Admin').order(created_at: :asc).last
admin.update
# Fails validation as before
2条答案
按热度按时间pu3pd22g1#
我不确定我是否完全理解了你的问题,但这部分代码中有一个问题:
验证是在类级别上配置的,因此它不能很好地与该模型上的更新一起工作(在后续的验证中不会重新评估)。
文档中指出,您可以使用块来包含,所以您也可以尝试这样做:
有些人会建议您甚至不进行这种验证,而是对该列进行数据库约束。
ua4mk5z42#
我相信你在这里误用了包含验证器。如果你想验证一个关联的模型存在,而不是它的id列有一个值,你可以用两种方法来做到这一点。在ActivRecord中,你可以使用一个存在验证器。
您还应该在数据库级别上使用foreign key constraint。这可以防止在关联表中没有相应记录时保存模型。
add_foreign_key:雇主,:公司
如果它通过ActiveRecord,并且没有具有给定
company_id
的公司记录,则数据库将抛出错误。