Reputation: 5862
I'm having a hard time trying to avoid duplicates in my database and really curious to know if I'm actually doing this correctly. In the example below, my technical reports actually work perfectly fine. So there's no duplicate nodes in the technical report, even if I try to create a duplicate manually.
However, I can't say the same for the nodes' vulns. When I import the exact same file (containing data) twice, I get duplicate Vulns for the same IP when I believe it's not supposed to happen.
So here are two models that I have:
#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
However, when I go to importing data, I still find myself with duplicates in the Vuln table. I've used rails c
to validate this as well.
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
When I go to call .uniq
it shows that there's only one entry.
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
Does anyone know what I'm doing wrong here? I'm not sure why this works for one model and not the other one. If I try to create two of the exact same Vuln records from rails c
CLI, it rolls back like it should have, but not when it's created otherwise.
EDIT
Looks like my issue is with activerecord-import instead. I'm not sure why but it imports nodes just fine, but it calls the "Class Create Many Without Validations Or Callbacks" when it goes to importing vulns. Guess because there's a lot more data or something. I think I have this sort of figured out for now. Perhaps I just need to write a quick method to validate the uniqueness manually since I don't want to get rid of the mass importing gem.
Upvotes: 1
Views: 657
Reputation: 2586
validates_uniqueness_of
can not ensure uniqueness in every case. Within the docs you can see an example for the race condition within this kind of validation. If it is realy needed you should also use an uniq constraint on database level.
Upvotes: 2