0

我有两个表,一个用于成员,另一个用于员工,两者都有一个称为id_number此属性的属性,不需要并且可以为空。

是否可以运行验证以确保 的唯一性id_number,以便如果添加的员工与id_number成员相同,反之亦然,则会出错。

我正在考虑编写自己的验证,但是每个实例的数据库都会非常慢,因为一些公司一次上传了 10 万个员工。

4

2 回答 2

1

是的,这可以通过您自己的验证来实现。我认为您必须访问数据库,否则您永远无法检查它是否已经存在。

def your_validation
  employee_ids = Employee.all.map(&:id_number)
  member_ids = Member.all.map(&:id_number)
  id = self.id_number
  if employee_ids.include?(id) || member_ids.include?(id)
    errors.add(:id_number, "is already taken")
  end
end

我认为为您的 id_number 添加索引会很好。

更新:上述方法可以更改为以下以提高性能:

def your_validation
  employee_ids = Employee.all.map(&:id_number)
  if employee_ids.include?(self.id_number)
    errors.add(:id_number, "is already taken")
  else
    member_ids = Member.all.map(&:id_number)
    if member_ids.include?(self.id_number)
      errors.add(:id_number, "is already taken")
    end
  end
end

第一个更干净,第二个应该更快。但是用大量的数据库条目和基准工具检查一下。

于 2013-08-22T07:59:54.750 回答
1

我想你会想要这样的东西:

def your_validation
  if self.id_number.present?
    if Employee.exists?(:id_number=>self.id_number) || Member.exists(:id_number=>self.id_number)
      errors.add(:id_number, "is already taken")
    end
  end
end

如果您在 id_number 列上有索引,则此检查应该运行得非常快,并且与 validates_uniqueness_of 将在单个表中使用的检查相同。当表变大时,涉及将所有 id 提取到 rails 的解决方案将开始遇到问题。

另一件需要注意的事情是,如果您的应用程序一次运行多个 Web 服务器实例,那么这些 Rails 侧检查不能 100% 保证唯一性,因为它们会受到线程之间的竞争。在这种情况下确保唯一性的唯一方法是使用内置在数据库中的工具或自己从排除重复的源(例如数据库序列)生成 id_numbers。

于 2014-05-05T18:01:58.370 回答