diff --git a/app/models/relationship.rb b/app/models/relationship.rb index ed90205ff..7002ebcf3 100644 --- a/app/models/relationship.rb +++ b/app/models/relationship.rb @@ -161,6 +161,21 @@ def self.create_unless_exists(source_id, target_id, relationship_type, options = exception_message = nil exception_class = nil if r.nil? + # Add to existing media cluster if source is already a target: + # If we're trying to create a relationship between C (target_id) and B (source_id), but there is already a relationship between A (source_id) and B (target_id), + # then, instead, create the relationship between A (source_id) and C (target_id) (so, if A's cluster contains B, then C comes in and our algorithm says C is similar + # to B, it is added to A's cluster). Exception: If the relationship between A (source_id) and B (target_id) is a suggestion, we should not create any relationship + # at all when trying to create a relationship between C (target_id) and B (source_id) (regardless if it’s a suggestion or a confirmed match) - but we should log that case. + existing = Relationship.where(target_id: source_id).first + unless existing.nil? + if existing.relationship_type == Relationship.suggested_type + error_msg = StandardError.new('Not creating relationship because requested source_id is already suggested to another item.') + CheckSentry.notify(error_msg, source_id: source_id, target_id: target_id, relationship_type: relationship_type, options: options) + return nil + end + source_id = existing.source_id + end + begin r = Relationship.new r.skip_check_ability = true diff --git a/test/models/relationship_2_test.rb b/test/models/relationship_2_test.rb index a95fc134f..4e8d976f7 100644 --- a/test/models/relationship_2_test.rb +++ b/test/models/relationship_2_test.rb @@ -463,4 +463,29 @@ def teardown end end end + + # If we're trying to create a relationship between C (target_id) and B (source_id), but there is already a relationship between A (source_id) and B (target_id), + # then, instead, create the relationship between A (source_id) and C (target_id) (so, if A's cluster contains B, then C comes in and our algorithm says C is similar + # to B, it is added to A's cluster). Exception: If the relationship between A (source_id) and B (target_id) is a suggestion, we should not create any relationship + # at all when trying to create a relationship between C (target_id) and B (source_id) (regardless if it’s a suggestion or a confirmed match) - but we should log that case. + test "should add to existing media cluster" do + t = create_team + a = create_project_media team: t + b = create_project_media team: t + c = create_project_media team: t + Relationship.create_unless_exists(a.id, b.id, Relationship.confirmed_type) + Relationship.create_unless_exists(b.id, c.id, Relationship.confirmed_type) + assert !Relationship.where(source: b, target: c).exists? + assert Relationship.where(source: a, target: b).exists? + assert Relationship.where(source: a, target: c).exists? + + a = create_project_media team: t + b = create_project_media team: t + c = create_project_media team: t + Relationship.create_unless_exists(a.id, b.id, Relationship.suggested_type) + Relationship.create_unless_exists(b.id, c.id, Relationship.confirmed_type) + assert !Relationship.where(source: b, target: c).exists? + assert Relationship.where(source: a, target: b).exists? + assert !Relationship.where(source: a, target: c).exists? + end end