diff --git a/lib/has_ontology_terms.rb b/lib/has_ontology_terms.rb index 7e72f0ad5..55db7b553 100644 --- a/lib/has_ontology_terms.rb +++ b/lib/has_ontology_terms.rb @@ -47,6 +47,26 @@ def has_ontology_terms(association_name, ontology: Edam::Ontology.instance, bran self.ontology_term_fields ||= [] self.ontology_term_fields << method.to_sym + define_method "#{links_method}=" do |links| + send(links_method).reset + current_links = send(links_method).to_a + to_keep = [] + + links.reject(&:blank?).map do |link| + idx = current_links.index { |l| l.term_uri == link.term_uri } + if idx + match = current_links.delete_at(idx) + to_keep << match + else + to_keep << link + end + end + + current_links.each(&:mark_for_destruction) # Now contains only redundant records + + super(to_keep) + end + # OntologyTerm objects define_method method do send(links_method).map(&:ontology_term).uniq diff --git a/test/models/event_test.rb b/test/models/event_test.rb index 5ec81805d..647fcf262 100644 --- a/test/models/event_test.rb +++ b/test/models/event_test.rb @@ -775,4 +775,33 @@ class EventTest < ActiveSupport::TestCase assert_equal 'Goblet', bioschemas[:provider].first['name'] assert_equal 'http://mygoblet.org', bioschemas[:provider].first['url'] end + + test 'does not destroy and recreate ontology term links' do + e = events(:scraper_user_event) + + # Via names + assert_difference('OntologyTermLink.count', 2) do + e.scientific_topic_names = %w[Proteins Chromosomes] + e.save! + assert_equal 2, e.scientific_topics.count + end + + ontology_term_links = e.ontology_term_links.to_a + + assert_no_difference('OntologyTermLink.count') do + e.scientific_topic_names = %w[Proteins Chromosomes] + e.save! + assert_equal 2, e.scientific_topics.count + end + + assert_equal ontology_term_links, e.reload.ontology_term_links.to_a + + assert_no_difference('OntologyTermLink.count') do + e.scientific_topic_names = %w[Proteins Biodiversity] + e.save! + assert_equal 2, e.scientific_topics.count + end + + assert_equal 1, (e.reload.ontology_term_links.to_a - ontology_term_links).length + end end