我很难在我的数据库中避免重复,并且真的很想知道我是否真的这样做了。在下面的示例中,我的技术报告实际上非常正常。因此,即使我尝试手动创建副本,技术报告中也没有重复的节点。
但是,我不能对节点说同样的话。 vulns。当我导入完全相同的文件(包含数据)两次时,当我认为它不应该发生时,我会得到相同IP的重复版本。
所以这里有两个模型:
#app/models/node.rb
class Node < ActiveRecord::Base
validates_uniqueness_of :technical_report_id, :scope => :ip
has_many :vulns, dependent: :destroy
end
#app/models/vuln.rb
class Vuln < ActiveRecord::Base
validates_uniqueness_of :node_id, :scope => [:master_finding_id, :vuln_finding_id, :additional_output, :port]
belongs_to :node
belongs_to :master_finding
belongs_to :vuln_finding
end
但是,当我去导入数据时,我仍然发现自己在Vuln表中有重复项。我已经使用rails c
来验证这一点。
irb(main):012:0> Vuln.where(node_id: 12).pluck(:master_finding_id, :additional_output, :vuln_finding_id).length
(0.4ms) SELECT `vulns`.`master_finding_id`, `vulns`.`additional_output`, `vulns`.`vuln_finding_id` FROM `vulns` WHERE `vulns`.`node_id` = 12
=> 2
当我打电话给.uniq
时,它显示只有一个条目。
irb(main):013:0> Vuln.where(node_id: 12).pluck(:master_finding_id, :additional_output, :vuln_finding_id).uniq.length
(0.5ms) SELECT `vulns`.`master_finding_id`, `vulns`.`additional_output`, `vulns`.`vuln_finding_id` FROM `vulns` WHERE `vulns`.`node_id` = 12
=> 1
有谁知道我在这里做错了什么?我不确定为什么这适用于一个型号而不是另一个型号。如果我尝试从rails c
CLI创建两个完全相同的Vuln记录,它会像它应该的那样回滚,但不会以其他方式创建。
修改
看起来我的问题是使用activerecord-import。我不确定为什么,但它导入节点就好了,但它调用了#34;类创建许多没有验证或回调&#34;什么时候进口东西。猜猜是因为有更多的数据或其他东西。我想我现在已经想到了这一点。也许我只需要编写一种快速方法来手动验证唯一性,因为我不想摆脱大量进口宝石。
答案 0 :(得分:2)
validates_uniqueness_of
无法确保每种情况下的唯一性。在docs中,您可以看到此类验证中的竞争条件示例。如果确实需要,您还应该在数据库级别使用uniq约束。