Skip to content

Commit

Permalink
Match has_one direction before deleting rel (#1662)
Browse files Browse the repository at this point in the history
* Match has_one direction before deleting rel

When relationship_corresponding_rel matches on the rel class name,
it stops on the first match, ignoring the direction parameter.

When target_class represents the to_node, direction is :in.

When the relationship is a has_one/has_many between a pair
of nodes of the same class, the match could find and return
the to_node's :out association first, causing
delete_reverse_has_one_relationship() to delete it.

Checking the direction first prevents that.

* Move shared_examples_for group into loop using it

per
#1662 (comment)

(cherry picked from commit ff2f8a5)
  • Loading branch information
bobmazanec authored and klobuczek committed Nov 5, 2021
1 parent d7bde6c commit 4a24ba3
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 2 deletions.
6 changes: 4 additions & 2 deletions lib/active_graph/node/has_n.rb
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,10 @@ def delete_has_one_rel!(rel)

def relationship_corresponding_rel(relationship, direction, target_class)
self.class.associations.find do |_key, assoc|
assoc.relationship_class_name == relationship.class.name ||
(assoc.relationship_type == relationship.type.to_sym && assoc.target_class == target_class && assoc.direction == direction)
assoc.direction == direction && (
assoc.relationship_class_name == relationship.class.name ||
(assoc.relationship_type == relationship.type.to_sym && assoc.target_class == target_class)
)
end
end

Expand Down
57 changes: 57 additions & 0 deletions spec/e2e/relationship_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -589,4 +589,61 @@ class ActiveRelSpecTypesInheritedRelClass < ActiveRelSpecTypesAutomaticRelType
end
end
end

context "between nodes of the same class" do
before(:each) do
clear_model_memory_caches

stub_node_class('NodeClass') do
has_one :out, :parent, rel_class: :IsParentOf
has_many :in, :children, rel_class: :IsParentOf
end

stub_relationship_class('IsParentOf') do
from_class :NodeClass
to_class :NodeClass
end

@gen0 = NodeClass.create
@gen1 = @gen2 = nil
end

after(:each) { [@gen0, @gen1, @gen2].compact.each(&:destroy) }

%i(all none).each do |uniqueness|
context "with creates_unique(:#{uniqueness})" do
before(:each) { IsParentOf.creates_unique uniqueness }

it "creates (gen1)-->(gen0)" do
@gen1 = NodeClass.create parent: @gen0

expect(@gen1.parent.id).to eq @gen0.id

expect(@gen0.children.count).to eq 1
expect(@gen0.children.first.id).to eq @gen1.id
end

context "given (gen1)-->(gen0)" do
before(:each) { @gen1 = NodeClass.create parent: @gen0 }

describe "#create (gen2)-->(gen1)" do
it "adds a new node and relationsihp without affecting (gen1)-->(gen0)" do
@gen2 = NodeClass.create parent: @gen1

expect(@gen2.parent.id).to eq @gen1.id

expect(@gen1.children.count).to eq 1
expect(@gen1.children.first.id).to eq @gen2.id

expect(@gen1.parent).to(be_present, "gen1 lost its parent")
expect(@gen1.parent.id).to eq @gen0.id

expect(@gen0.children.count).to eq 1
expect(@gen0.children.first.id).to eq @gen1.id
end
end
end
end
end
end
end

0 comments on commit 4a24ba3

Please sign in to comment.