diff --git a/app/models/code.rb b/app/models/code.rb index f0bdb42..682f027 100644 --- a/app/models/code.rb +++ b/app/models/code.rb @@ -23,6 +23,15 @@ def self.histogram(context) codes.inject({}) {|accumulator,code| accumulator[code.values[0]] ||= 0; accumulator[code.values[0]] += code.values[1]; accumulator} end + def self.orphans + query_as(:c).with('c, count{(c)-[:EXPERIENCES]-(:Persona)} AS ct').where('ct = 0').return('c, ct').map(&:first) + end + + def self.reap_orphans + orphans = query_as(:c).with('c, count{(c)-[:EXPERIENCES]-(:Persona)} AS ct').where('ct = 0').return('c, ct').map(&:first) + orphans.each(&:destroy) + end + private def sanitize diff --git a/app/models/identity.rb b/app/models/identity.rb index 6a81432..14529f8 100644 --- a/app/models/identity.rb +++ b/app/models/identity.rb @@ -19,6 +19,15 @@ def self.histogram(context) identities.inject({}) {|accumulator,identity| accumulator[identity.values[0]] ||= 0; accumulator[identity.values[0]] += identity.values[1]; accumulator} end + def self.orphans + query_as(:i).with('i, count{(i)-[:IDENTIFIES_WITH]-(:Persona)} AS ct').where('ct = 0').return('i, ct').map(&:first) + end + + def self.reap_orphans + orphans = query_as(:i).with('i, count{(i)-[:IDENTIFIES_WITH]-(:Persona)} AS ct').where('ct = 0').return('i, ct').map(&:first) + orphans.each(&:destroy) + end + private def strip_whitespace diff --git a/app/models/services/export_to_graph.rb b/app/models/services/export_to_graph.rb index 3dd269a..d9189af 100644 --- a/app/models/services/export_to_graph.rb +++ b/app/models/services/export_to_graph.rb @@ -16,8 +16,6 @@ def initialize(case_id) def perform return false unless kase - # Destroy the existing persona so that neo4j will reap orphaned nodes like Codes and Identities. - Persona.find_or_initialize_by(case_id: kase.id).destroy populate_codes populate_identities return true @@ -41,6 +39,7 @@ def populate_codes next if question.is_identity? context = question.context.name + persona.codes = [] response.raw_codes.compact.uniq.each do |name| if code = Code.find_or_create_by(name: name, context: context) @@ -49,6 +48,9 @@ def populate_codes end end end + + # Clean up any Codes that are no longer associated with a Persona. + Code.reap_orphans end # Creates Identity nodes and connects them to the associated Persona. @@ -58,6 +60,7 @@ def populate_identities next unless question.is_identity? context = question.context.name + persona.identities = [] response.raw_codes.compact.uniq.each do |name| if identity = Identity.find_or_create_by(name: name.strip, context: context) @@ -66,6 +69,9 @@ def populate_identities end end end + + # Clean up any Identities that are no longer associated with a Persona. + Identity.reap_orphans end end diff --git a/spec/models/services/export_to_graph_spec.rb b/spec/models/services/export_to_graph_spec.rb index 687de5c..a5fed7b 100644 --- a/spec/models/services/export_to_graph_spec.rb +++ b/spec/models/services/export_to_graph_spec.rb @@ -8,10 +8,12 @@ allow(Persona).to receive(:find_or_create_by).and_return(persona) allow(Persona).to receive(:find_or_initialize_by).and_return(persona) - allow(persona).to receive(:destroy) allow(Identity).to receive(:find_or_create_by).and_return(identity) + allow(Identity).to receive(:reap_orphans) + allow(Code).to receive(:find_or_create_by).and_return(code) + allow(Code).to receive(:reap_orphans) allow(response_1).to receive(:question).and_return(question_1) allow(response_2).to receive(:question).and_return(question_2)