Rails validates_uniqueness_of似乎并不适合我

时间:2016-08-20 03:28:58

标签: ruby-on-rails

我很难在我的数据库中避免重复,并且真的很想知道我是否真的这样做了。在下面的示例中,我的技术报告实际上非常正常。因此,即使我尝试手动创建副本,技术报告中也没有重复的节点。

但是,我不能对节点说同样的话。 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;什么时候进口东西。猜猜是因为有更多的数据或其他东西。我想我现在已经想到了这一点。也许我只需要编写一种快速方法来手动验证唯一性,因为我不想摆脱大量进口宝石。

1 个答案:

答案 0 :(得分:2)

validates_uniqueness_of无法确保每种情况下的唯一性。在docs中,您可以看到此类验证中的竞争条件示例。如果确实需要,您还应该在数据库级别使用uniq约束。