diff --git a/lib/neo4j/active_node/query/query_proxy.rb b/lib/neo4j/active_node/query/query_proxy.rb index aff5d4a50..dd1039fb4 100644 --- a/lib/neo4j/active_node/query/query_proxy.rb +++ b/lib/neo4j/active_node/query/query_proxy.rb @@ -79,7 +79,7 @@ def to_cypher # To add a relationship for the node for the association on this QueryProxy def <<(other_node) - associate(other_node, {}) + create(other_node, {}) self end @@ -90,14 +90,22 @@ def [](index) self.to_a[index] end - def associate(other_node, properties) + def create(other_nodes, properties) if @association - raise ArgumentError, "Node must be of the association's class when model is specified" if @model && other_node.class != @model + other_nodes = [other_nodes].flatten - _association_query_start(:start) - .match(end: other_node.class) - .where(end: {neo_id: other_node.neo_id}) - .create("start#{_association_arrow(properties, true)}end").exec + raise ArgumentError, "Node must be of the association's class when model is specified" if @model && other_nodes.any? {|other_node| other_node.class != @model } + + other_nodes.each do |other_node| + Neo4j::Transaction.run do |tx| + other_node.save if not other_node.persisted? + + _association_query_start(:start) + .match(end: other_node.class) + .where(end: {neo_id: other_node.neo_id}) + .create("start#{_association_arrow(properties, true)}end").exec + end + end else raise "Can only create associations on associations" end diff --git a/spec/e2e/has_n_spec.rb b/spec/e2e/has_n_spec.rb index da48979ff..2d37df9d7 100644 --- a/spec/e2e/has_n_spec.rb +++ b/spec/e2e/has_n_spec.rb @@ -12,6 +12,8 @@ #knows_type = clazz_b UniqueClass.create do include Neo4j::ActiveNode + property :name + has_many :both, :friends, model_class: false has_many :out, :knows, model_class: self has_many :in, :knows_me, origin: :knows, model_class: self @@ -114,19 +116,48 @@ end end - describe 'me.friends.associate(other, since: 1994)' do - it 'creates a new relationship with given properties' do - r = node.friends.associate(friend1, since: 1994) + describe 'me.friends#create(other, since: 1994)' do + describe "creating relationships to existing nodes" do + it 'creates a new relationship when given existing nodes and given properties' do + node.friends.create(friend1, since: 1994) + + r = node.rel(dir: :outgoing, type: '#friends') + + r[:since].should eq(1994) + end + + it 'creates new relationships when given an array of nodes and given properties' do + node.friends.create([friend1, friend2], since: 1995) - r = node.rel(dir: :outgoing, type: '#friends') + rs = node.rels(dir: :outgoing, type: '#friends') - r[:since].should eq(1994) + rs.map(&:end_node).should =~ [friend1, friend2] + rs.each do |r| + r[:since].should eq(1995) + end + end end - end - describe "me.friends.create(name: 'Joe')" do - # TODO: Should be able to create both relationship and node off of an association - # Maybe .create / .push for creating relationship / node (respectively) - # Maybe should be able to create relationships by passing either node object or hash of values + describe "creating relationships and nodes at the same time" do + it 'creates a new relationship when given unpersisted node and given properties' do + node.friends.create(clazz_a.new(name: 'Brad'), {since: 1996}) + + r = node.rel(dir: :outgoing, type: '#friends') + + r[:since].should eq(1996) + r.end_node.name.should == 'Brad' + end + + it 'creates a new relationship when given an array of unpersisted nodes and given properties' do + node.friends.create([clazz_a.new(name: 'James'), clazz_a.new(name: 'Cat')], {since: 1997}) + + rs = node.rels(dir: :outgoing, type: '#friends') + + rs.map(&:end_node).map(&:name).should =~ ['James', 'Cat'] + rs.each do |r| + r[:since].should eq(1997) + end + end + end end end diff --git a/spec/e2e/query_spec.rb b/spec/e2e/query_spec.rb index 31ffe9492..b48dd888a 100644 --- a/spec/e2e/query_spec.rb +++ b/spec/e2e/query_spec.rb @@ -243,8 +243,8 @@ class Teacher context 'othmar likes moster trucks more than samuels' do before(:each) do - samuels.interests.associate(monster_trucks, intensity: 1) - othmar.interests.associate(monster_trucks, intensity: 11) + samuels.interests.create(monster_trucks, intensity: 1) + othmar.interests.create(monster_trucks, intensity: 11) end # Should get both