簡體   English   中英

Rails交叉模型驗證

[英]Rails cross model validation

我有兩個表一個用於成員,另一個用於員工,兩個表都有一個名為id_number的屬性,這個屬性不是必需的,可以為null。

是否可以運行驗證以確保id_number的唯一性,以便如果為員工添加與成員相同的id_number ,反之亦然,則會產生錯誤。

我正在考慮編寫自己的驗證,但是每個實例的db都會非常慢,因為有些公司一次上傳了數千名員工。

是的,您可以通過自己的驗證。 我認為你必須打到數據庫,否則你永遠無法檢查它是否已經存在。

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

第一個更清潔,第二個應該更快。 但是請使用大量的數據庫條目和基准工具來檢查這一點。

我想你會想要這樣的東西:

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 side check不能100%保證唯一性,因為它們會受到線程之間的競爭。 在這種情況下確保唯一性的唯一方法是使用數據庫中內置的工具,或者從排除重復項的源(例如數據庫序列)自己生成id_numbers。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM