diff --git a/README.rdoc b/README.rdoc index 9ed7c10cd..202035b63 100644 --- a/README.rdoc +++ b/README.rdoc @@ -75,12 +75,23 @@ a social network, a relationship type could be KNOWS. If a relationship of the t that probably represents two people that know each other. A lot of the semantics, the meaning, of a node space is encoded in the relationship types of the application. +=== Creating Nodes + Example of creating a neo4j node: require "rubygems" require 'neo4j' - node = Neo4j::Node.new + Neo4j::Transaction.run do + node = Neo4j::Node.new + end + +=== Transactions + +Almost all Neo4j operation must be wrapped in a transaction as shown above. +In the following examples we assume that the operations are inside an Neo4j transaction. + +=== Setting Properties Example of setting properties @@ -90,16 +101,20 @@ Example of setting properties node[:hungry] = false node[4] = 3.14 +=== Getting Properties Example of getting properties node[:name] # => 'foo' + +=== Creating Relationships Example of creating a relationship node1 = Neo4j::Node.new node2 = Neo4j::Node.new node1.relationships.outgoing(:friends) << node2 # connects node1 to node2 with relationship type 'friends' +=== Accessing Relationships Example of getting relationships node1.relationships.empty? # => false @@ -113,12 +128,14 @@ Example of getting relationships node1.relationships.incoming(:friends).nodes.first # => node1 first node of relationship type 'friends' node2.relationships.incoming(:friends).first # => a relationship object between node1 and node2 +=== Properties on Relationships Example of setting properties on relationships rel = node1.relationships(:friends).first rel[:since] = 1982 node1.relationships.first[:since] # => 1982 (there is only one relationship defined on node1 in this example) +=== The Node and NodeMixin Here is the complete implemenation of the Neo4j::Node class module Neo4j @@ -624,10 +641,7 @@ Example of how declare a class that has this behaviour: === Create a Node -If a block is provided then the creation of the instance will be performed in an -transaction, see below for more information on transactions. - - node = MyNode.new { } + node = MyNode.new === Delete a Node diff --git a/examples/imdb/find_actors.rb b/examples/imdb/find_actors.rb index 282e2fb54..8079be044 100644 --- a/examples/imdb/find_actors.rb +++ b/examples/imdb/find_actors.rb @@ -1,6 +1,7 @@ $LOAD_PATH << File.expand_path(File.dirname(__FILE__) + "/../../lib") #require "rubygems" -require "neo4j" +require "neo4j" +require "neo4j/extensions/reindexer" require "model" Neo4j::Config[:storage_path] = DB_NEO_DIR diff --git a/lib/extensions/reindexer.rb b/lib/neo4j/extensions/reindexer.rb similarity index 91% rename from lib/extensions/reindexer.rb rename to lib/neo4j/extensions/reindexer.rb index 0a0459b68..0141fa7fd 100644 --- a/lib/extensions/reindexer.rb +++ b/lib/neo4j/extensions/reindexer.rb @@ -13,7 +13,7 @@ def update_index n.update_index end end - + # Returns node instances of this class. # # :api: public @@ -78,6 +78,11 @@ def self.instance # Add this so it can add it self as listener - Neo4j.event_handler.add(IndexNode) + def self.load_reindexer + Neo4j.event_handler.add(IndexNode) + # incase we already have started + Neo4j::Transaction.run { IndexNode.on_neo_started(Neo4j.instance) } if Neo4j.running? + end + load_reindexer end diff --git a/lib/extensions/tx_tracker.rb b/lib/neo4j/extensions/tx_tracker.rb similarity index 92% rename from lib/extensions/tx_tracker.rb rename to lib/neo4j/extensions/tx_tracker.rb index 48ee29061..b73eb5152 100644 --- a/lib/extensions/tx_tracker.rb +++ b/lib/neo4j/extensions/tx_tracker.rb @@ -125,9 +125,13 @@ def to_s end # Add this so it can add it self as listener - Neo4j.event_handler.add_filter(TxNode) - Neo4j.event_handler.add_filter(TxNodeCreated) - Neo4j.event_handler.add(TxNodeList) + def self.load_tx_tracker + Neo4j.event_handler.add_filter(TxNode) + Neo4j.event_handler.add_filter(TxNodeCreated) + Neo4j.event_handler.add(TxNodeList) + + Neo4j::Transaction.run { TxNodeList.on_neo_started(Neo4j.instance) } if Neo4j.running? + end # if neo is already run we have to let txnodelist have a chance to add it self # TxNodeList.on_neo_started(Neo4j.instance) if Neo4j.running? @@ -147,4 +151,7 @@ def self.load_uuid(uuid) # if it does not exist we need to create a new node end + + load_tx_tracker + end \ No newline at end of file diff --git a/lib/neo4j/mixins/node.rb b/lib/neo4j/mixins/node.rb index d0c5ef86b..620bfeba3 100644 --- a/lib/neo4j/mixins/node.rb +++ b/lib/neo4j/mixins/node.rb @@ -20,7 +20,6 @@ module NodeMixin # Initialize the the neo node for this instance. # Will create a new transaction if one is not already running. - # If a block is given a new transaction will be created. # # Does # * sets the neo property 'classname' to self.class.to_s @@ -29,13 +28,11 @@ module NodeMixin # :api: public def initialize(*args) # was a neo java node provided ? - Transaction.run do - if args.length == 1 and args[0].kind_of?(org.neo4j.api.core.Node) - init_with_node(args[0]) - else - init_without_node - yield self if block_given? - end + if args.length == 1 and args[0].kind_of?(org.neo4j.api.core.Node) + init_with_node(args[0]) + else + init_without_node + init_node(*args) if self.respond_to?(:init_node) end # must call super with no arguments so that chaining of initialize method will work super() @@ -80,7 +77,7 @@ def init_without_node def set_property(name, value) $NEO_LOGGER.debug{"set property '#{name}'='#{value}'"} old_value = get_property(name) - + if value.nil? remove_property(name) elsif self.class.marshal?(name) @@ -290,7 +287,6 @@ def relationships end - # Check if the given relationship exists # Returns true if there are one or more relationships from this node to other nodes # with the given relationship. @@ -347,7 +343,7 @@ def update_index end - transactional :property?, :set_property, :get_property, :remove_property, :delete + transactional :initialize, :property?, :set_property, :get_property, :remove_property, :delete # @@ -564,7 +560,6 @@ def remove_index(*keys) end - # :api: private def index_property(prop) indexer.add_index_on_property(prop) @@ -637,7 +632,6 @@ def #{rel_type}(&block) end - # Creates a new outgoing relationship. # # :api: private diff --git a/lib/neo4j/mixins/relationship.rb b/lib/neo4j/mixins/relationship.rb index d2fd91ee8..53e4df51e 100644 --- a/lib/neo4j/mixins/relationship.rb +++ b/lib/neo4j/mixins/relationship.rb @@ -15,8 +15,7 @@ module RelationshipMixin # # :api: public def initialize(*args) - Transaction.run {init_with_rel(args[0])} unless Transaction.running? - init_with_rel(args[0]) if Transaction.running? + init_with_rel(args[0]) # must call super with no arguments so that chaining of initialize method will work super() @@ -117,7 +116,7 @@ def neo_relationship_id @internal_r.getId() end - transactional :property?, :set_property, :get_property, :delete + transactional :initialize, :property?, :set_property, :get_property, :delete # # Adds classmethods in the ClassMethods module diff --git a/lib/neo4j/mixins/transactional.rb b/lib/neo4j/mixins/transactional.rb index 25139db17..7ab40ff80 100644 --- a/lib/neo4j/mixins/transactional.rb +++ b/lib/neo4j/mixins/transactional.rb @@ -6,6 +6,7 @@ module Neo4j module TransactionalMixin def transactional(*methods) + return # return unless (Neo4j::Config[:auto_tx]) methods.each do |name| orig_name = (name.to_s == '<<') ? '_append' : "_original_#{name}" diff --git a/lib/neo4j/neo.rb b/lib/neo4j/neo.rb index b433ca776..abbac133a 100644 --- a/lib/neo4j/neo.rb +++ b/lib/neo4j/neo.rb @@ -91,7 +91,7 @@ def self.event_handler @event_handler ||= EventHandler.new end - + # # Allows run and stop the Neo4j service # Contains global ćonstants such as location of the neo storage and index files @@ -101,6 +101,8 @@ def self.event_handler # class Neo + extend Neo4j::TransactionalMixin + # # ref_node : the reference, ReferenceNode, node, wraps a org.neo4j.api.core.NeoService#getReferenceNode # @@ -114,7 +116,6 @@ def start Neo4j.event_handler.neo_started(self) end $NEO_LOGGER.info{ "Started neo. Database storage located at '#{@db_storage}'"} - end # @@ -139,10 +140,8 @@ def begin_transaction # def find_node(id) begin - Transaction.run do - neo_node = @neo.getNodeById(id) - load_node(neo_node) - end + neo_node = @neo.getNodeById(id) + load_node(neo_node) rescue org.neo4j.api.core.NotFoundException nil end @@ -194,6 +193,7 @@ def tx_manager @neo.getConfig().getTxModule().getTxManager() end + transactional :find_node end end diff --git a/lib/neo4j/search_result.rb b/lib/neo4j/search_result.rb index b6c91304d..634e70467 100644 --- a/lib/neo4j/search_result.rb +++ b/lib/neo4j/search_result.rb @@ -32,7 +32,6 @@ def query_params end def each - Transaction.run do hits.each do |doc| id = doc[:id] node = Neo4j.instance.find_node(id.to_i) @@ -40,15 +39,12 @@ def each raise LuceneIndexOutOfSyncException.new("lucene found node #{id} but it does not exist in neo") if node.nil? yield node end - end end def [](n) doc = hits[n] - Transaction.run do id = doc[:id] Neo4j.instance.find_node(id.to_i) - end end def sort_by(*fields) diff --git a/lib/neo4j/transaction.rb b/lib/neo4j/transaction.rb index a364f9984..a4b945b4d 100644 --- a/lib/neo4j/transaction.rb +++ b/lib/neo4j/transaction.rb @@ -127,6 +127,10 @@ def running? def failure? current.failure? end + + def finish + current.finish if running? + end end diff --git a/lib/neo4j/transactions_node.rb b/lib/neo4j/transactions_node.rb deleted file mode 100644 index 8eaf443a2..000000000 --- a/lib/neo4j/transactions_node.rb +++ /dev/null @@ -1,23 +0,0 @@ -module Neo4j - - class TransactionsNode - include NodeMixin - - # when a node is added to the transactions relationships - # neo4j adds automatically a _next and _prev to added nodes - # TransactionsNode.new - # tx.transactions.each - return them as ordered - has_list :transactions - - def add_tx(tx) - TxNode.new - end - end - - - class TxNode - include NodeMixin - - property - end -end \ No newline at end of file diff --git a/test/neo4j/has_list_spec.rb b/test/neo4j/has_list_spec.rb index fc6af12b8..4ae870c4c 100644 --- a/test/neo4j/has_list_spec.rb +++ b/test/neo4j/has_list_spec.rb @@ -21,15 +21,18 @@ def to_s describe "ListNode (Neo4j::NodeMixin#has_list)" do - # Called before each example. - before(:each) do - # Do nothing - end + before(:all) do + start + end - # Called after each example. - after(:each) do - # Do nothing - end + before(:each) do + Neo4j::Transaction.new + end + + after(:each) do + Neo4j::Transaction.finish + end + it "should contain items after append one item to a list (#<<)" do list = ListNode.new diff --git a/test/neo4j/has_n_spec.rb b/test/neo4j/has_n_spec.rb index ea7ee9bf0..453c96251 100644 --- a/test/neo4j/has_n_spec.rb +++ b/test/neo4j/has_n_spec.rb @@ -11,11 +11,16 @@ start end - after(:all) do - stop + before(:each) do + Neo4j::Transaction.new + end + + after(:each) do + Neo4j::Transaction.finish end + # ---------------------------------------------------------------------------- # adding relationships with << # @@ -76,13 +81,14 @@ class TestNode t1.friends << t2 << t3 # then t2 should be a friend of t1 - t1.friends.to_a.should include(t2,t3) + t1.friends.to_a.should include(t2, t3) end it "should be allowed in subclasses" do undefine_class :SubNode # make sure it is not already defined - class SubNode < TestNode; end + class SubNode < TestNode; + end sub = SubNode.new t = TestNode.new sub.friends << t @@ -102,35 +108,37 @@ class PersonNode has_n(:known_by).from(PersonNode, :friends) end - @n0 = PersonNode.new - @n1 = PersonNode.new - @n11 = PersonNode.new - @n111 = PersonNode.new - @n12 = PersonNode.new - @n112 = PersonNode.new - @n1121 = PersonNode.new - @n0.friends << @n1 << @n12 - @n1.friends << @n11 << @n12 - @n11.friends << @n111 << @n112 - @n112.friends << @n1121 + Neo4j::Transaction.run do + @n0 = PersonNode.new + @n1 = PersonNode.new + @n11 = PersonNode.new + @n111 = PersonNode.new + @n12 = PersonNode.new + @n112 = PersonNode.new + @n1121 = PersonNode.new + @n0.friends << @n1 << @n12 + @n1.friends << @n11 << @n12 + @n11.friends << @n111 << @n112 + @n112.friends << @n1121 + end end it "should work with outgoing nodes of depth 2" do nodes = @n1.friends.depth(2) - nodes.should include(@n11,@n12,@n112) - nodes.should_not include(@n0,@n1,@n1121) + nodes.should include(@n11, @n12, @n112) + nodes.should_not include(@n0, @n1, @n1121) end it "should work with outgoing nodes of depth 3" do nodes = @n1.friends.depth(3) - nodes.should include(@n11,@n12,@n112, @n1121) - nodes.should_not include(@n0,@n1) + nodes.should include(@n11, @n12, @n112, @n1121) + nodes.should_not include(@n0, @n1) end it "should work with outgoing nodes to the end of graph" do nodes = @n1.friends.depth(:all) - nodes.should include(@n11,@n12,@n112, @n1121) - nodes.should_not include(@n0,@n1) + nodes.should include(@n11, @n12, @n112, @n1121) + nodes.should_not include(@n0, @n1) end it "should work with incoming nodes of depth 2" do @@ -153,12 +161,17 @@ class PersonNode before(:all) do undefine_class :Customer, :Order, :CustOrderRel - class Customer; end + class Customer; + end class Order include Neo4j::NodeMixin property :date, :order_id has_one(:customer).from(Customer, :orders) + + def to_s + "Order #{order_id}" + end end class CustOrderRel @@ -231,11 +244,16 @@ class Customer # pending "filter not implemented yet, see ticket 17" # given customer = Customer.new - order1 = Order.new{|n| n.order_id = '1'} - order2 = Order.new{|n| n.order_id = '2'} - order3 = Order.new{|n| n.order_id = '3'} + order1 = Order.new + order2 = Order.new + order3 = Order.new customer.orders << order1 << order2 << order3 + order1.order_id = '1' + order2.order_id = '2' + order3.order_id = '3' + + customer.orders.each {|x| puts x} # when result = customer.orders{ order_id == '2'}.to_a diff --git a/test/neo4j/has_one_spec.rb b/test/neo4j/has_one_spec.rb index ade5cabb4..40ad442f0 100644 --- a/test/neo4j/has_one_spec.rb +++ b/test/neo4j/has_one_spec.rb @@ -26,9 +26,13 @@ class Address end - after(:all) do - stop - end + before(:each) do + Neo4j::Transaction.new + end + + after(:each) do + Neo4j::Transaction.finish + end it "should create a relationship with assignment like node1.rel = node2" do # given diff --git a/test/neo4j/index_spec.rb b/test/neo4j/index_spec.rb deleted file mode 100644 index 15339cc47..000000000 --- a/test/neo4j/index_spec.rb +++ /dev/null @@ -1,36 +0,0 @@ -$LOAD_PATH << File.expand_path(File.dirname(__FILE__) + "/../../lib") -$LOAD_PATH << File.expand_path(File.dirname(__FILE__) + "/..") - -require 'neo4j' -require 'neo4j/spec_helper' - - -describe "Neo4j & Lucene Transaction Synchronization:" do - before(:all) do - start - undefine_class :TestNode - class TestNode - include Neo4j::NodeMixin - property :name - index :name - end - end - after(:all) do - stop - end - - it "should reindex when a property has been changed" do - # given - n1 = TestNode.new - n1.name = 'hi' - TestNode.find(:name => 'hi').should include(n1) - - - # when - n1.name = "oj" - - # then - TestNode.find(:name => 'hi').should_not include(n1) - TestNode.find(:name => 'oj').should include(n1) - end -end \ No newline at end of file diff --git a/test/neo4j/indexer_spec.rb b/test/neo4j/indexer_spec.rb index bd0fa3987..8dba30cd7 100644 --- a/test/neo4j/indexer_spec.rb +++ b/test/neo4j/indexer_spec.rb @@ -11,6 +11,8 @@ describe Indexer, " given Employee.salary in employed_by Company is indexed" do before(:all) do undefine_class :Employee, :Company + start + class Employee include Neo4j::NodeMixin property :salary @@ -28,6 +30,15 @@ class Company @employee_indexer.add_index_in_relationship_on_property(Company, 'employees', 'employed_by', 'salary') end + + before(:each) do + Neo4j::Transaction.new + end + + after(:each) do + Neo4j::Transaction.finish + end + it "should update index when salary changes on one employee" do employee = Employee.new employee.salary = 10000 @@ -101,6 +112,15 @@ class Company end + before(:each) do + Neo4j::Transaction.new + end + + after(:each) do + Neo4j::Transaction.finish + end + + it "should include each employees salary in the company index" do employee1 = Employee.new employee1.salary = 1 @@ -119,7 +139,7 @@ class Company index.size.should == 1 index[0][:id].should == company.neo_node_id index[0][:'employees.salary'].size.should == 2 - index[0][:'employees.salary'].should include(1,2) + index[0][:'employees.salary'].should include(1, 2) end it "should update index when salary changes on one employee" do @@ -187,6 +207,15 @@ class Person end end + + before(:each) do + Neo4j::Transaction.new + end + + after(:each) do + Neo4j::Transaction.finish + end + def create_indexer Indexer.clear_all_instances indexer = Indexer.instance Person @@ -202,7 +231,7 @@ def create_indexer node1.age = 42 index = [] - indexer = create_indexer + indexer = create_indexer indexer.stub!(:lucene_index).and_return index # when @@ -240,7 +269,7 @@ def create_indexer # then index_node2[:id].should == node2.neo_node_id index_node2[:'friends.age'].size.should == 2 - index_node2[:'friends.age'].should include(42,44) + index_node2[:'friends.age'].should include(42, 44) end @@ -263,8 +292,8 @@ def create_indexer # find which index belongs to which node index.size.should == 2 - index_node2,index_node3 = index - index_node2,index_node3 = index_node3,index_node2 unless index_node2[:id] == node2.neo_node_id + index_node2, index_node3 = index + index_node2, index_node3 = index_node3, index_node2 unless index_node2[:id] == node2.neo_node_id # then index_node2[:id].should == node2.neo_node_id diff --git a/test/neo4j/neo_spec.rb b/test/neo4j/neo_spec.rb index cfeb03a09..8c805176c 100644 --- a/test/neo4j/neo_spec.rb +++ b/test/neo4j/neo_spec.rb @@ -22,11 +22,16 @@ class Foo end res = Foo.find(:name => 'kalle') res.size.should == 0 - f = Foo.new - f.name = 'kalle' - res = Foo.find(:name => 'kalle') - res.size.should == 1 - res[0].name.should == 'kalle' + Neo4j::Transaction.run do + f = Foo.new + f.name = 'kalle' + end + + Neo4j::Transaction.run do + res = Foo.find(:name => 'kalle') + res.size.should == 1 + res[0].name.should == 'kalle' + end end end @@ -38,13 +43,13 @@ class Foo after(:each) do stop end - + it "should return a new neo instance if neo has been stopped" do x = Neo4j.instance Neo4j.stop Neo4j.instance.should_not == x end - + it "should have a reference node" do ref_node = Neo4j.instance.ref_node ref_node.should_not be_nil @@ -55,18 +60,23 @@ class Foo class TestNode include Neo4j::NodeMixin end - t1 = TestNode.new + Neo4j::Transaction.run do + t1 = TestNode.new + + # when + t2 = Neo4j.instance.find_node(t1.neo_node_id) - # when - t2 = Neo4j.instance.find_node(t1.neo_node_id) + # then + t1.should == t2 + end - # then - t1.should == t2 end it "should not find a node that does not exist" do - n = Neo4j.instance.find_node(10) - n.should be_nil + Neo4j::Transaction.run do + n = Neo4j.instance.find_node(10) + n.should be_nil + end end - + end diff --git a/test/neo4j/node_lucene_spec.rb b/test/neo4j/node_lucene_spec.rb index 09872e1c0..b4db8f07a 100644 --- a/test/neo4j/node_lucene_spec.rb +++ b/test/neo4j/node_lucene_spec.rb @@ -3,7 +3,7 @@ require 'neo4j' require 'neo4j/spec_helper' -require 'extensions/reindexer' +require 'neo4j/extensions/reindexer' describe "Neo4j.start" do @@ -14,16 +14,22 @@ class TestNode property :name, :age index :name end + Neo4j.load_reindexer end - before(:each) { start } after(:each) { stop } + after(:all) do + Neo4j.event_handler.remove(Neo4j::IndexNode) # avoid side effects on using this extension + end + it "should keep index on filesystem if specifed" do Lucene::Config[:store_on_file] = true - t = TestNode.new - t.name = 'hello' + Neo4j::Transaction.run do + t = TestNode.new + t.name = 'hello' + end File.exist?(Lucene::Config[:storage_path]).should be_true end @@ -35,20 +41,20 @@ class TestNode # when Lucene::Config[:store_on_file] = false - t = TestNode.new - t.name = 'hello' + Neo4j::Transaction.run { TestNode.new.name = 'hello'} # then File.exist?(LUCENE_INDEX_LOCATION).should be_false end end - + describe "Neo4j & Lucene Transaction Synchronization:" do before(:all) do start + Neo4j.load_reindexer undefine_class :TestNode - class TestNode + class TestNode include Neo4j::NodeMixin property :name, :age index :name, :age @@ -56,7 +62,8 @@ class TestNode end after(:all) do stop - end + end + it "should specify which properties to index using NodeMixin#index method" do TestNode.indexer.property_indexer.properties.should include(:name, :age) @@ -70,42 +77,48 @@ class TestNode Neo4j::Transaction.run do |t| n1 = TestNode.new n1.name = 'hello' - + # when t.failure end - + # then n1.should_not be_nil TestNode.find(:name => 'hello').should_not include(n1) end - + it "should reindex when a property has been changed" do # given - n1 = TestNode.new - n1.name = 'hi' + n1 = Neo4j::Transaction.run do + n1 = TestNode.new + n1.name = 'hi' + n1 + end TestNode.find(:name => 'hi').should include(n1) - - + + # when - n1.name = "oj" - + Neo4j::Transaction.run { n1.name = "oj" } + # then TestNode.find(:name => 'hi').should_not include(n1) TestNode.find(:name => 'oj').should include(n1) end - + it "should remove the index when a node has been deleted" do # given - n1 = TestNode.new - n1.name = 'remove' - + n1 = Neo4j::Transaction.run do + n1 = TestNode.new + n1.name = 'remove' + n1 + end + # make sure we can find it TestNode.find(:name => 'remove').should include(n1) - + # when - n1.delete - + Neo4j::Transaction.run { n1.delete } + # then TestNode.find(:name => 'remove').should_not include(n1) end @@ -114,6 +127,7 @@ class TestNode describe "A node with no lucene index" do before(:all) do start + Neo4j.load_reindexer class TestNodeWithNoIndex include Neo4j::NodeMixin end @@ -134,17 +148,25 @@ class TestNodeWithNoIndex describe "Find with sorting" do before(:all) do start + Neo4j.load_reindexer undefine_class :Person7 class Person7 include Neo4j::NodeMixin property :name, :city index :name index :city + + def init_node(name, city) + self.name = name + self.city = city + end + end + Neo4j::Transaction.run do + @kalle = Person7.new('kalle', 'malmoe') + @andreas = Person7.new('andreas', 'malmoe') + @sune = Person7.new('sune', 'malmoe') + @anders = Person7.new('anders', 'malmoe') end - @kalle = Person7.new {|p| p.name = 'kalle'; p.city = 'malmoe'} - @andreas = Person7.new {|p| p.name = 'andreas'; p.city = 'malmoe'} - @sune = Person7.new {|p| p.name = 'sune'; p.city = 'malmoe'} - @anders = Person7.new {|p| p.name = 'anders'; p.city = 'malmoe'} end after(:all) do @@ -164,9 +186,9 @@ class Person7 persons = Person7.find(:city => 'malmoe') persons.size.should == 4 sorted = persons[0] == @anders && - persons[1] == @andreas && - persons[2] == @kalle && - persons[3] == @sune + persons[1] == @andreas && + persons[2] == @kalle && + persons[3] == @sune sorted.should == false end @@ -176,24 +198,32 @@ class Person7 describe "Find Nodes using Lucene and tokenized index" do before(:all) do start + Neo4j.load_reindexer undefine_class :Person class Person include Neo4j::NodeMixin property :name, :name2 index :name, :tokenized => true index :name2, :tokenized => false # default + + def init_node(name) + self[:name] = name + self[:name2] = name + end + def to_s "Person '#{self.name}'" end end names = ['Andreas Ronge', 'Kalle Kula', 'Laban Surename', 'Sune Larsson', 'hej hopp'] @foos = [] - names.each {|n| - node = Person.new - node.name = n - node.name2 = n - @foos << node - } + Neo4j::Transaction.run do + names.each {|n| + node = Person.new(n) + @foos << node + } + end + Neo4j::Transaction.new end after(:all) do @@ -246,6 +276,7 @@ def to_s describe "Find nodes using Lucene" do before(:all) do start + Neo4j.load_reindexer class TestNode include Neo4j::NodeMixin property :name, :age, :male, :height @@ -255,26 +286,29 @@ class TestNode index :height, :type => Float end @foos = [] - 5.times {|n| - node = TestNode.new - node.name = "foo#{n}" - node.age = n # "#{n}" - node.male = (n == 0) - node.height = n * 0.1 - @foos << node - } - @bars = [] - 5.times {|n| - node = TestNode.new - node.name = "bar#{n}" - node.age = n # "#{n}" - node.male = (n == 0) - node.height = n * 0.1 - @bars << node - } - - @node100 = TestNode.new {|n| n.name = "node"; n.age = 100} - + Neo4j::Transaction.run do + 5.times {|n| + node = TestNode.new + node.name = "foo#{n}" + node.age = n # "#{n}" + node.male = (n == 0) + node.height = n * 0.1 + @foos << node + } + @bars = [] + 5.times {|n| + node = TestNode.new + node.name = "bar#{n}" + node.age = n # "#{n}" + node.male = (n == 0) + node.height = n * 0.1 + @bars << node + } + + @node100 = TestNode.new + @node100.name = "node" + @node100.age = 100 + end end after(:all) do @@ -348,6 +382,7 @@ class TestNode before(:each) do undefine_class :PersonNode start + Neo4j.load_reindexer class PersonNode include Neo4j::NodeMixin property :name @@ -356,7 +391,7 @@ class PersonNode index :born, :type => Date end end - + after(:each) do stop end @@ -364,10 +399,12 @@ class PersonNode it "should find using a date query" do result = PersonNode.find("born:[20080427 TO 20100203]") result.size.should == 0 - node = PersonNode.new - node.born.should be_nil - node.name = 'kalle' - node.born = Date.new 2008,05,06 + Neo4j::Transaction.run do + node = PersonNode.new + node.born.should be_nil + node.name = 'kalle' + node.born = Date.new 2008, 05, 06 + end # when result = PersonNode.find("born:[20080427 TO 20100203]") @@ -379,6 +416,7 @@ class PersonNode before(:each) do undefine_class :PersonNode start + Neo4j.load_reindexer class PersonNode include Neo4j::NodeMixin property :name @@ -395,11 +433,13 @@ class PersonNode it "should find using a date query" do result = PersonNode.find("since:[200804271504 TO 201002031534]") result.size.should == 0 - node = PersonNode.new - node.since.should be_nil - node.name = 'kalle' - # only UTC Times are supported - node.since = DateTime.civil 2008,04,27,15,25,59 + Neo4j::Transaction.run do + node = PersonNode.new + node.since.should be_nil + node.name = 'kalle' + # only UTC Times are supported + node.since = DateTime.civil 2008, 04, 27, 15, 25, 59 + end # when result = PersonNode.find("since:[200804271504 TO 201002031534]") diff --git a/test/neo4j/node_mixin_spec.rb b/test/neo4j/node_mixin_spec.rb index 909d4fed7..3992e7264 100644 --- a/test/neo4j/node_mixin_spec.rb +++ b/test/neo4j/node_mixin_spec.rb @@ -11,12 +11,19 @@ # describe 'NodeMixin#initialize' do - before(:each) do - stop - undefine_class :TestNode, :SubNode # must undefine this since each spec defines it + + before(:all) do start end + before(:each) do + Neo4j::Transaction.new + end + + after(:each) do + Neo4j::Transaction.finish + end + it "should accept no arguments" do class TestNode1 include Neo4j::NodeMixin @@ -29,17 +36,22 @@ class TestNode1 class TestNode2 include Neo4j::NodeMixin attr_reader :foo + property :baaz - def initialize + def initialize(baaz) + super @foo = "bar" + self.baaz = baaz end + end # when - n = TestNode2.new + n = TestNode2.new('hajhaj') # then n.foo.should == 'bar' + n[:baaz].should == 'hajhaj' end @@ -71,6 +83,18 @@ class TestNode4 describe 'NodeMixin properties' do + before(:all) do + start + end + + before(:each) do + Neo4j::Transaction.new + end + + after(:each) do + Neo4j::Transaction.finish + end + it "should behave like a hash" do n = Neo4j::Node.new n[:a] = 'a' @@ -100,12 +124,18 @@ class TestNode include Neo4j::NodeMixin property :name, :age end + + start end - after(:all) do - stop + before(:each) do + Neo4j::Transaction.new end - + + after(:each) do + Neo4j::Transaction.finish + end + it "should be able to update a node from a value obejct" do # given t = TestNode.new @@ -146,14 +176,23 @@ class TestNode describe 'NodeMixin#equality (==)' do - after(:all) do - stop - end - before(:all) do + start + NODES = 5 @nodes = [] - NODES.times {@nodes << Neo4j::Node.new} + Neo4j::Transaction.run do + NODES.times { @nodes << Neo4j::Node.new} + end + + end + + before(:each) do + Neo4j::Transaction.new + end + + after(:each) do + Neo4j::Transaction.finish end it "should be == another node only if it has the same node id" do @@ -179,9 +218,20 @@ class TestNode # describe "Neo4j::Node#delete" do - after(:all) do - stop + before(:all) do + start end + + before(:each) do + Neo4j::Transaction.new + end + + after(:each) do + Neo4j::Transaction.finish + end + + + it "should delete all relationships as well" do # given t1 = Neo4j::Node.new diff --git a/test/neo4j/node_traverser_spec.rb b/test/neo4j/node_traverser_spec.rb index e9503e166..e48565e21 100644 --- a/test/neo4j/node_traverser_spec.rb +++ b/test/neo4j/node_traverser_spec.rb @@ -12,28 +12,32 @@ start end - after(:all) do - stop - end + before(:each) do + Neo4j::Transaction.new + end + + after(:each) do + Neo4j::Transaction.finish + end + + - - # ---------------------------------------------------------------------------- # traversing outgoing and incoming nodes # - + describe 'traversing outgoing and incoming nodes' do before(:all) do undefine_class :TestNode # make sure it is not already defined - - class TestNode + + class TestNode include Neo4j::NodeMixin has_n :friends has_n :parents property :name end - end - + end + it "should find all outgoing nodes" do # given t1 = TestNode.new @@ -42,12 +46,12 @@ class TestNode # when outgoing = t1.traverse.outgoing(:friends).to_a - + # then outgoing.size.should == 1 outgoing[0].should == t2 end - + it "should find all incoming nodes" do # given t1 = TestNode.new @@ -100,29 +104,29 @@ class TestNode t1 = TestNode.new t2 = TestNode.new t3 = TestNode.new - + t1.friends << t2 t1.friends << t3 # when and then - t1.traverse.both(:friends).to_a.should include(t2,t3) - t1.traverse.outgoing(:friends).to_a.should include(t2,t3) + t1.traverse.both(:friends).to_a.should include(t2, t3) + t1.traverse.outgoing(:friends).to_a.should include(t2, t3) t2.traverse.incoming(:friends).to_a.should include(t1) t3.traverse.incoming(:friends).to_a.should include(t1) t1.traverse.both(:friends).to_a.size.should == 2 end - + it "should find incoming nodes of a specific type" do # given t1 = TestNode.new t2 = TestNode.new t3 = TestNode.new - + t1.friends << t2 t1.friends << t3 # when and then - t1.traverse.outgoing(:friends).to_a.should include(t2,t3) + t1.traverse.outgoing(:friends).to_a.should include(t2, t3) t2.traverse.incoming(:friends).to_a.should include(t1) t3.traverse.incoming(:friends).to_a.should include(t1) end @@ -162,7 +166,7 @@ class TestNode # when and then t_outgoing = t.traverse.outgoing(:friends).depth(:all).to_a t_outgoing.size.should == 5 - t_outgoing.should include(t1,t11, t111,t12,t2) + t_outgoing.should include(t1, t11, t111, t12, t2) end it "should find incoming nodes of depth 2" do @@ -186,9 +190,12 @@ class TestNode it "should find outgoing nodes using a filter function that will be evaluated in the context of the current node" do # given - a = TestNode.new {|n| n.name = 'a'} - b = TestNode.new {|n| n.name = 'b'} - c = TestNode.new {|n| n.name = 'c'} + a = TestNode.new + b = TestNode.new + c = TestNode.new + a.name = "a" + b.name = "b" + c.name = "c" a.friends << b << c # when @@ -217,13 +224,19 @@ class TestNode property :name end - # given - @a = TestNode.new {|n| n.name = 'a'} - @b = TestNode.new {|n| n.name = 'b'} - @c = TestNode.new {|n| n.name = 'c'} - @p = TestNode.new {|n| n.name = 'p'} - @a.friends << @b << @c - @a.parents << @p + Neo4j::Transaction.run do + # given + @a = TestNode.new + @b = TestNode.new + @c = TestNode.new + @p = TestNode.new + @a.name = 'a' + @b.name = 'b' + @c.name = 'c' + @p.name = 'p' + @a.friends << @b << @c + @a.parents << @p + end end it "should work with the TraversalPosition#current_node parameter" do @@ -241,7 +254,7 @@ class TestNode # then result.size.should == 2 - result.should include(@b,@c) + result.should include(@b, @c) end it "should work with the TraversalPosition#last_relationship_traversed parameter" do @@ -310,22 +323,25 @@ def self.create(name) end - @europe = Location.create 'europe' - @sweden = Location.create 'sweden' - @denmark = Location.create 'denmark' - @malmoe = Location.create 'malmoe' - @stockholm = Location.create 'stockholm' - @europe.contains << @sweden << @denmark - @sweden.contains << @malmoe << @stockholm - - @sweden_trip = Trip.create 'See all of sweden in 14 days' - @city_tour = Trip.create 'The city tour specialist' - @malmoe_trip = Trip.create 'Malmoe city sightseeing by boat' - - @sweden.trips << @sweden_trip - @malmoe.trips << @malmoe_trip - @malmoe.trips << @city_tour - @stockholm.trips << @city_tour # the same city tour is available both in malmoe and stockholm + Neo4j::Transaction.run do + @europe = Location.create 'europe' + @sweden = Location.create 'sweden' + @denmark = Location.create 'denmark' + @malmoe = Location.create 'malmoe' + @stockholm = Location.create 'stockholm' + @europe.contains << @sweden << @denmark + @sweden.contains << @malmoe << @stockholm + + @sweden_trip = Trip.create 'See all of sweden in 14 days' + @city_tour = Trip.create 'The city tour specialist' + @malmoe_trip = Trip.create 'Malmoe city sightseeing by boat' + + @sweden.trips << @sweden_trip + @malmoe.trips << @malmoe_trip + @malmoe.trips << @city_tour + @stockholm.trips << @city_tour # the same city tour is available both in malmoe and stockholm + end + end it "should raise an exception if no type of direction is specified for the traversal" do @@ -370,5 +386,5 @@ def self.create(name) end end - + end \ No newline at end of file diff --git a/test/neo4j/order_spec.rb b/test/neo4j/order_spec.rb index 35fd96e28..578eb8d9b 100644 --- a/test/neo4j/order_spec.rb +++ b/test/neo4j/order_spec.rb @@ -63,6 +63,11 @@ class CustomerA has_n(:orders).from(Order, :customer) # :zero_or_more, :orders, Order, :customer # contains incoming relationship of type 'orders' has_n(:friends).to(CustomerA) + def init_node(name='hej', age=102) + self.name = name + self.age = age + end + def to_s "CustomerA [name=#{name}]" end @@ -77,17 +82,26 @@ def to_s end end - + before(:each) do start end - + after(:each) do stop - end + end describe "create relationship" do + + before(:each) do + Neo4j::Transaction.new + end + + after(:each) do + Neo4j::Transaction.finish + end + it "should allow to create a new dynamic relationship to an order from a customer instance" do c = CustomerA.new o = Order.new @@ -114,147 +128,215 @@ def to_s end end - + describe "#find" do it "should find one customers who has made two orders with a certain total cost" do - customer = CustomerA.new - order1 = Order.new - order1.total_cost = 100 - order1.customer = customer - - order2 = Order.new - order2.total_cost = 42 - order2.customer = customer - - r = CustomerA.find('orders.total_cost' => '100', 'orders.total_cost' => '42') - r.size.should == 1 - r.should include(customer) + customer = nil + Neo4j::Transaction.run do + customer = CustomerA.new + order1 = Order.new + order1.total_cost = 100 + order1.customer = customer + + order2 = Order.new + order2.total_cost = 42 + order2.customer = customer + end + + Neo4j::Transaction.run do + r = CustomerA.find('orders.total_cost' => '100', 'orders.total_cost' => '42') + r.size.should == 1 + r.should include(customer) + end end - + it "should find two customers who has made two orders with a certain total cost" do - customer1 = CustomerA.new - order1 = Order.new - order1.total_cost = 100 - order1.customer = customer1 - - customer2 = CustomerA.new - order2 = Order.new - order2.total_cost = 42 - order2.customer = customer2 - - r = CustomerA.find('orders.total_cost' => 100) - r.size.should == 1 - r.should include(customer1) - - r = CustomerA.find('orders.total_cost' => 42) - r.size.should == 1 - r.should include(customer2) + customer1 = customer2 = nil + Neo4j::Transaction.run do + customer1 = CustomerA.new + order1 = Order.new + order1.total_cost = 100 + order1.customer = customer1 + + customer2 = CustomerA.new + order2 = Order.new + order2.total_cost = 42 + order2.customer = customer2 + end + + Neo4j::Transaction.run do + r = CustomerA.find('orders.total_cost' => 100) + r.size.should == 1 + r.should include(customer1) + + r = CustomerA.find('orders.total_cost' => 42) + r.size.should == 1 + r.should include(customer2) + end end it "should not find a customer with 1 order of a total cost of 200 if that order has been deleted" do - customer = CustomerA.new - order = Order.new - order.total_cost = '200' - order.customer = customer - - CustomerA.find('orders.total_cost' => '200').size.should == 1 + order = nil + Neo4j::Transaction.run do + customer = CustomerA.new + order = Order.new + order.total_cost = '200' + order.customer = customer + end + + Neo4j::Transaction.run do + CustomerA.find('orders.total_cost' => '200').size.should == 1 + end # when - order.delete - + Neo4j::Transaction.run do + order.delete + end + # then - CustomerA.find('orders.total_cost' => '200').size.should == 0 + Neo4j::Transaction.run do + CustomerA.find('orders.total_cost' => '200').size.should == 0 + end end it "should find customer who has a friends of age 30, setting relationship first and then age" do - c1 = CustomerA.new - c2 = CustomerA.new - c3 = CustomerA.new - - c1.friends << c2 - c2.friends << c3 - c3.friends << c1 - - c1.age = 29 - c2.age = 30 - c3.age = 31 - - res = CustomerA.find('friends.age' => 30) - res.size.should == 2 - res.should include(c1, c3) + c1 = c2 = c3 = nil + Neo4j::Transaction.run do + c1 = CustomerA.new + c2 = CustomerA.new + c3 = CustomerA.new + + c1.friends << c2 + c2.friends << c3 + c3.friends << c1 + + c1.age = 29 + c2.age = 30 + c3.age = 31 + end + + Neo4j::Transaction.run do + res = CustomerA.find('friends.age' => 30) + res.size.should == 2 + res.should include(c1, c3) + end end - - + + it "should find customer who has a friend with age 30, setting age first and then relationship" do - c1 = CustomerA.new {|n| n.name = 'c1'; n.age = 29} - c2 = CustomerA.new {|n| n.name = 'c2'; n.age = 30} - c3 = CustomerA.new {|n| n.name = 'c3'; n.age = 31} - - c1.friends << c2 - c2.friends << c3 - c3.friends << c1 - - res = CustomerA.find('friends.age' => 30) - res.size.should == 2 - res.should include(c1, c3) + c1 = c2 = c3 = nil + + Neo4j::Transaction.run do + c1 = CustomerA.new('c1', 29) + c2 = CustomerA.new('c2', 30) + c3 = CustomerA.new('c3', 31) + + c1.friends << c2 + c2.friends << c3 + c3.friends << c1 + end + + Neo4j::Transaction.run do + res = CustomerA.find('friends.age' => 30) + res.size.should == 2 + res.should include(c1, c3) + end end - + it "should find all customer of age 30" do - c1 = CustomerA.new {|n| n.name = 'c1'; n.age = 29} - c2 = CustomerA.new {|n| n.name = 'c2'; n.age = 30} - c3 = CustomerA.new {|n| n.name = 'c3'; n.age = 30} - - c = CustomerA.find(:age => 30) - c.size.should == 2 - c.should include(c2, c3) + c1 = c2 = c3 = nil + Neo4j::Transaction.run do + c1 = CustomerA.new('c1', 29) + c2 = CustomerA.new('c2', 30) + c3 = CustomerA.new('c3', 30) + end + + Neo4j::Transaction.run do + c = CustomerA.find(:age => 30) + c.size.should == 2 + c.should include(c2, c3) + end end - - - + + + it "should not find a customer by name if the name has changed" do - c1 = CustomerA.new {|n| n.name = 'c1'; n.age = 29} - - c = CustomerA.find(:name => 'c1') - c.size.should == 1 - c.should include(c1) - + c1 = Neo4j::Transaction.run do + CustomerA.new('c1', 29) + end + + Neo4j::Transaction.run do + c = CustomerA.find(:name => 'c1') + c.size.should == 1 + c.should include(c1) + end + + # when - c1.name = 'c2' - + Neo4j::Transaction.run do + c1.name = 'c2' + end + + # then - c = CustomerA.find(:name => 'c1') - c.size.should == 0 + Neo4j::Transaction.run do + c = CustomerA.find(:name => 'c1') + c.size.should == 0 + end + end - + it "should find a customer by the new name if the name has changed" do - c1 = CustomerA.new {|n| n.name = 'c1'; n.age = 29} - - c = CustomerA.find(:name => 'c1') - c.size.should == 1 - c.should include(c1) - + c1 = Neo4j::Transaction.run do + CustomerA.new('c1', 29) + end + + c = Neo4j::Transaction.run do + c = CustomerA.find(:name => 'c1') + c.size.should == 1 + c.should include(c1) + c + end + + # when - c1.name = 'c2' - + Neo4j::Transaction.run do + c1.name = 'c2' + end + # then - c = CustomerA.find(:name => 'c2') - c.size.should == 1 - c.should include(c1) + Neo4j::Transaction.run do + c = CustomerA.find(:name => 'c2') + c.size.should == 1 + c.should include(c1) + end end - - - + + + it "should not find any customer if they all have been deleted" do - c1 = CustomerA.new {|n| n.name = 'c1'; n.age = 29} - c = CustomerA.find(:age => 29) - c.size.should == 1 - c1.delete - c = CustomerA.find(:age => 29) - c.size.should == 0 + c1 = Neo4j::Transaction.run do + CustomerA.new('c1', 29) + end + + Neo4j::Transaction.run do + c = CustomerA.find(:age => 29) + c.size.should == 1 + end + + Neo4j::Transaction.run do + c1.delete + end + + Neo4j::Transaction.run do + c = CustomerA.find(:age => 29) + c.size.should == 0 + end + end - + end end diff --git a/test/neo4j/person_spec.rb b/test/neo4j/person_spec.rb index 0146d22c4..3e229b9c3 100644 --- a/test/neo4j/person_spec.rb +++ b/test/neo4j/person_spec.rb @@ -22,75 +22,103 @@ class Person after(:all) do stop - end - + end + it "should be possible to create a new instance" do - person = Person.new - result = Neo4j.instance.find_node person.neo_node_id - result.should == person + person = Neo4j::Transaction.run do + Person.new + end + + Neo4j::Transaction.run do + result = Neo4j.instance.find_node person.neo_node_id + result.should == person + end + end it "should find persons who has friends with a specific age" do - me = Person.new - me.age = 10 - you = Person.new - you.age = 20 + me = nil + Neo4j::Transaction.run do + + me = Person.new + me.age = 10 + you = Person.new + you.age = 20 + + me.friends << you + end - me.friends << you - # when - res = Person.find('friends.age' => '20') + Neo4j::Transaction.run do + res = Person.find('friends.age' => '20') - # then - res.size.should == 1 - res[0].should == me + # then + res.size.should == 1 + res[0].should == me + end end it "should be possible to find it given its name" do - person1 = Person.new - person1.name = 'kalle' - person2 = Person.new - person2.name = "sune" + person1 = person2 = nil + Neo4j::Transaction.run do + + person1 = Person.new + person1.name = 'kalle' + person2 = Person.new + person2.name = "sune" + end # when - result = Person.find(:name => 'kalle') - - # then - result.should include(person1) - result.should_not include(person2) - result.size.should == 1 + Neo4j::Transaction.run do + + result = Person.find(:name => 'kalle') + + # then + result.should include(person1) + result.should_not include(person2) + result.size.should == 1 + end end - - + + it "should be possible to add a friend" do - person1 = Person.new - person1.name = 'kalle' - - person2 = Person.new - person2.name = "sune" - - # when - person1.friends << person2 - - # then - person1.friends.to_a.should include(person2) + person1 = person2 = nil + Neo4j::Transaction.run do + person1 = Person.new + person1.name = 'kalle' + + person2 = Person.new + person2.name = "sune" + + # when + person1.friends << person2 + end + + + Neo4j::Transaction.run do + # then + person1.friends.to_a.should include(person2) + end end it "should be possible to remove a friend" do - # given - person1 = Person.new - person1.name = 'kalle' - person2 = Person.new - person2.name = "sune" - person1.friends << person2 + person1 = person2 = nil + Neo4j::Transaction.run do + # given + person1 = Person.new + person1.name = 'kalle' + person2 = Person.new + person2.name = "sune" + person1.friends << person2 - # when - person1.relationships[person2].delete - - # then - person1.friends.to_a.should_not include(person2) + # when + person1.relationships[person2].delete + + # then + person1.friends.to_a.should_not include(person2) + end end - + end diff --git a/test/neo4j/property_spec.rb b/test/neo4j/property_spec.rb index 2516041d2..ab85353c3 100644 --- a/test/neo4j/property_spec.rb +++ b/test/neo4j/property_spec.rb @@ -7,6 +7,7 @@ class MyPropertyData attr_accessor :x + def initialize(x) @x = x end @@ -23,8 +24,6 @@ class MyNode end - after(:all) { stop } - it "should have no info about any properties" do MyNode.properties_info.should be_empty MyNode.properties_info[:since].should be_nil @@ -53,8 +52,13 @@ class MyNode end end + before(:each) do + Neo4j::Transaction.new + end - after(:all) { stop } + after(:each) do + Neo4j::Transaction.finish + end it "should know the type of declared properties" do MyNode.properties_info.size.should == 3 @@ -71,7 +75,7 @@ class MyNode it "should marshal Date properties" do n = MyNode.new - date = Date.new 2008,12,15 + date = Date.new 2008, 12, 15 n.since = date n.since.class.should == Date n.since.should == date @@ -90,11 +94,16 @@ class MyNode include Neo4j::NodeMixin property :fooz end - @node = MyNode.new + @node = Neo4j::Transaction.run { MyNode.new } end + before(:each) do + Neo4j::Transaction.new + end - after(:all) { stop } + after(:each) do + Neo4j::Transaction.finish + end it "should have no type info" do MyNode.properties_info.size.should == 1 @@ -140,11 +149,16 @@ class Stuff property :stuff, :type => Object property :foo end + Neo4j::Transaction.new @node = Stuff.new end - after(:each) { stop } + after(:each) do + Neo4j::Transaction.finish + stop + end + it "should know the type of the property" do Stuff.properties_info[:stuff].class.should == Hash @@ -158,9 +172,9 @@ class Stuff it "should allow to set properties of type Array" do # when - array = [1,"2",3.14] + array = [1, "2", 3.14] @node.stuff = array - + # then node = Neo4j.load(@node.neo_node_id) node.stuff.class == Array @@ -190,6 +204,7 @@ class Stuff describe 'Neo4j properties' do before(:each) do start + Neo4j::Transaction.new undefine_class :TestNode # make sure it is not already defined class TestNode include Neo4j::NodeMixin @@ -198,12 +213,15 @@ class TestNode @node = TestNode.new end - after(:each) { stop } - + after(:each) do + Neo4j::Transaction.finish + stop + end + it "should know which properties has been set" do @node.p1 = "val1" @node.p2 = "val2" - + @node.props.should have_key('p1') @node.props.should have_key('p2') end @@ -217,7 +235,7 @@ class TestNode TestNode.property?(:p3).should be_false TestNode.property?("ojojoj").should be_false end - + it "should allow to get a property that has not been set" do @node.should_not be_property('p1') @node.p1.should be_nil @@ -228,22 +246,22 @@ class TestNode @node.should respond_to(:neo_node_id) @node.neo_node_id.should be_kind_of(Fixnum) end - + it "should have a property for the ruby class it represent" do @node.classname.should be == TestNode.to_s end - + it "should allow to set any property" do # given @node.p1 = "first" - + # when @node.p1 = "Changed it" - + # then @node.p1.should =='Changed it' end - + it "should allow to set properties to nil" do @node.p1 = nil @node.p1.should == nil @@ -281,32 +299,32 @@ class TestNode @node.should_not be_property('p1') @node.p1.should be_nil end - + it "should generated setter and getters methods" do # when p = TestNode.new {} - + # then - p.methods.should include('p1','p2') + p.methods.should include('p1', 'p2') p.methods.should include("p1=", 'p2=') end - + it "should automatically be defined on subclasses" do undefine_class :SubNode # make sure it is not already defined - + # given class SubNode < TestNode property :salary end - + # when p = SubNode.new {} - + # then - p.methods.should include("p1",'p2') + p.methods.should include("p1", 'p2') p.methods.should include("salary", "salary=") end - - + + end diff --git a/test/neo4j/readme_spec.rb b/test/neo4j/readme_spec.rb index 962f7d170..b61d3290e 100644 --- a/test/neo4j/readme_spec.rb +++ b/test/neo4j/readme_spec.rb @@ -6,13 +6,17 @@ describe "Readme Examples" do - #before(:all) do - # stop - #end - # Called after each example. - after(:all) do - stop + before(:all) do + start + end + + before(:each) do + Neo4j::Transaction.new + end + + after(:each) do + Neo4j::Transaction.finish end it "should run: Example of setting properties" do @@ -25,7 +29,7 @@ it "should run: Example of getting properties" do node = Neo4j::Node.new node[:name] = 'foo' - node[:name].should == 'foo' + node[:name].should == 'foo' end it "should run: Example of creating a relationship" do @@ -38,7 +42,7 @@ node1 = Neo4j::Node.new node2 = Neo4j::Node.new node1.relationships.outgoing(:friends) << node2 - + node1.relationships.nodes.include?(node2).should be_true # => true - it implements enumerable and other methods node1.relationships.empty?.should be_false # => false node1.relationships.first.should_not be_nil # => the first relationship this node1 has which is between node1 and node2 diff --git a/test/neo4j/ref_node_spec.rb b/test/neo4j/ref_node_spec.rb index 1f7e535f7..e8aa5ee47 100644 --- a/test/neo4j/ref_node_spec.rb +++ b/test/neo4j/ref_node_spec.rb @@ -3,19 +3,6 @@ require 'neo4j' require 'neo4j/spec_helper' -require 'extensions/reindexer' - - - -class RefTestNode - include Neo4j::NodeMixin - property :name, :age -end - -class RefTestNode2 - include Neo4j::NodeMixin -end - describe 'ReferenceNode' do before(:all) do @@ -26,49 +13,38 @@ class RefTestNode2 stop end + before(:each) do - # clean up all references from index node - puts "Neo4j::IndexNode.instance.relationships= #{Neo4j::IndexNode.instance.relationships}" - Neo4j::IndexNode.instance.relationships.outgoing.each {|r| r.delete} + Neo4j::Transaction.new end - - it "has a reference to a created node" do - #should only have a reference to the reference node - n = RefTestNode.new - n.name = 'hoj' - # then - Neo4j::IndexNode.instance.relationships.nodes.should include(n) - Neo4j::IndexNode.instance.relationships.to_a.size.should == 1 + after(:each) do + Neo4j::Transaction.finish end + + it "can allow to create my own relationships from the reference node" do + # given + Neo4j.ref_node.relationships.outgoing(:myfoo).empty?.should be_true + node = Neo4j::Node.new - it "has a reference to all created nodes" do - Neo4j::IndexNode.instance.relationships.outgoing.to_a.should be_empty - node1 = RefTestNode.new - node2 = RefTestNode2.new - node3 = RefTestNode2.new + # when + Neo4j.ref_node.relationships.outgoing(:myfoo) << node # then - Neo4j::IndexNode.instance.relationships.outgoing(:RefTestNode).nodes.should include(node1) - Neo4j::IndexNode.instance.relationships.outgoing(:RefTestNode2).nodes.should include(node2, node3) - Neo4j::IndexNode.instance.relationships.outgoing(:RefTestNode).nodes.to_a.size.should == 1 - Neo4j::IndexNode.instance.relationships.outgoing(:RefTestNode2).nodes.to_a.size.should == 2 - - RefTestNode.all.nodes.to_a.size.should == 1 - RefTestNode2.all.nodes.to_a.size.should == 2 + Neo4j.ref_node.relationships.outgoing(:myfoo).nodes.should include(node) + Neo4j.ref_node.relationships.outgoing(:myfoo).to_a.size.should == 1 end - it "can allow to create my own relationships (with has_n,has_one) from the reference node" do - node = RefTestNode.new - node.name = "ojoj" - + + it "can allow to create my own properties on the reference node" do + # given + Neo4j.ref_node[:kalle].should be_nil + # when - Neo4j.ref_node.class.has_one :my_node - + Neo4j.ref_node[:kalle] = 123 + # then - Neo4j.ref_node.my_node = node - Neo4j.ref_node.my_node.should == node - Neo4j.ref_node.my_node.name.should == "ojoj" + Neo4j.ref_node[:kalle].should == 123 end end diff --git a/test/neo4j/reindexer_spec.rb b/test/neo4j/reindexer_spec.rb index 2cfdea57f..40ab12658 100644 --- a/test/neo4j/reindexer_spec.rb +++ b/test/neo4j/reindexer_spec.rb @@ -3,20 +3,70 @@ require 'neo4j' require 'neo4j/spec_helper' -require 'extensions/reindexer' +require 'neo4j/extensions/reindexer' + + + +class ReindexerTestNode + include Neo4j::NodeMixin + property :name, :age +end + +class ReindexerTestNode2 + include Neo4j::NodeMixin +end describe "Reindexer (NodeMixin#all)" do before(:each) do start + Neo4j.load_reindexer + Neo4j::Transaction.new + Neo4j::IndexNode.instance.relationships.each {|r| r.delete unless r.start_node == Neo4j.ref_node} undefine_class :TestNode # must undefine this since each spec defines it end after(:each) do + Neo4j::Transaction.finish stop end + before(:all) do + Neo4j.event_handler.add(Neo4j::IndexNode) # incase it has been disabled by an RSpec + end + + after(:all) do + Neo4j.event_handler.remove(Neo4j::IndexNode) # avoid side effects on using this extension + end + + + it "has a reference to a created node" do + #should only have a reference to the reference node + n = ReindexerTestNode.new + n.name = 'hoj' + + # then + Neo4j::IndexNode.instance.relationships.nodes.should include(n) + Neo4j::IndexNode.instance.relationships.to_a.size.should == 1 + end + + it "has a reference to all created nodes" do + Neo4j::IndexNode.instance.relationships.outgoing.to_a.should be_empty + node1 = ReindexerTestNode.new + node2 = ReindexerTestNode2.new + node3 = ReindexerTestNode2.new + + # then + Neo4j::IndexNode.instance.relationships.outgoing(:ReindexerTestNode).nodes.should include(node1) + Neo4j::IndexNode.instance.relationships.outgoing(:ReindexerTestNode2).nodes.should include(node2, node3) + Neo4j::IndexNode.instance.relationships.outgoing(:ReindexerTestNode).nodes.to_a.size.should == 1 + Neo4j::IndexNode.instance.relationships.outgoing(:ReindexerTestNode2).nodes.to_a.size.should == 2 + + ReindexerTestNode.all.nodes.to_a.size.should == 1 + ReindexerTestNode2.all.nodes.to_a.size.should == 2 + end + it "should return all node instances" do class TestNode include Neo4j::NodeMixin diff --git a/test/neo4j/relation_traverser_spec.rb b/test/neo4j/relation_traverser_spec.rb index 4b902b16e..e3af27438 100644 --- a/test/neo4j/relation_traverser_spec.rb +++ b/test/neo4j/relation_traverser_spec.rb @@ -12,9 +12,15 @@ start end - after(:all) do - stop - end + + before(:each) do + Neo4j::Transaction.new + end + + after(:each) do + Neo4j::Transaction.finish + end + @@ -73,6 +79,7 @@ class TestNode # then outgoing.size.should == 1 + outgoing[0].should_not be_nil outgoing[0].end_node.should == t2 outgoing[0].start_node.should == t1 end @@ -87,9 +94,9 @@ class TestNode outgoing = t2.relationships.incoming.to_a # then - outgoing.size.should == 2 # 2 since we also have a relationship to ref node - outgoing[1].end_node.should == t2 - outgoing[1].start_node.should == t1 + outgoing.size.should == 1 + outgoing[0].end_node.should == t2 + outgoing[0].start_node.should == t1 end it "should find no incoming or outgoing nodes when there are none" do @@ -98,7 +105,7 @@ class TestNode t2 = TestNode.new # when and then - t2.relationships.incoming.to_a.size.should == 1 # since we also have a relationship to ref node + t2.relationships.incoming.to_a.size.should == 0 t2.relationships.outgoing.to_a.size.should == 0 end @@ -109,7 +116,7 @@ class TestNode t1.friends << t2 # when and then - t1.relationships.incoming.to_a.size.should == 1 # since we also have a relationship to ref node + t1.relationships.incoming.to_a.size.should == 0 t2.relationships.outgoing.to_a.size.should == 0 end @@ -139,7 +146,7 @@ class TestNode t1.relationships.both.outgoing.nodes.to_a.should include(t2,t3) t2.relationships.both.incoming.nodes.to_a.should include(t1) t3.relationships.both.incoming.nodes.to_a.should include(t1) - t1.relationships.both.nodes.to_a.size.should == 3 # since we also have a relationship to ref node + t1.relationships.both.nodes.to_a.size.should == 2 end it "should find incoming nodes of a specific type" do diff --git a/test/neo4j/spec_helper.rb b/test/neo4j/spec_helper.rb index a6cabc375..3e60f0534 100644 --- a/test/neo4j/spec_helper.rb +++ b/test/neo4j/spec_helper.rb @@ -11,36 +11,49 @@ NEO_STORAGE = Dir::tmpdir + "/neo_storage" LUCENE_INDEX_LOCATION = Dir::tmpdir + "/lucene" +Lucene::Config[:storage_path] = LUCENE_INDEX_LOCATION +Lucene::Config[:store_on_file] = false +Neo4j::Config[:storage_path] = NEO_STORAGE def delete_db - # make sure we finish all transactions - Neo4j::Transaction.current.finish if Neo4j::Transaction.running? - - # delete all configuration - Lucene::Config.delete_all - # delete db on filesystem FileUtils.rm_rf Neo4j::Config[:storage_path] # NEO_STORAGE FileUtils.rm_rf Lucene::Config[:storage_path] unless Lucene::Config[:storage_path].nil? end - -def start +def reset_config + # reset configuration + Lucene::Config.delete_all Lucene::Config[:storage_path] = LUCENE_INDEX_LOCATION - Neo4j::Config[:storage_path] = NEO_STORAGE - - # set default configuration Lucene::Config[:store_on_file] = false + + Neo4j::Config.delete_all Neo4j::Config[:storage_path] = NEO_STORAGE +end +def start + # stop it - just in case + stop + + delete_db + + reset_config + # start neo + Neo4j.event_handler.remove_all # TODO need a nicer way to test extension - loading and unloading Neo4j.start end def stop + # make sure we finish all transactions + Neo4j::Transaction.finish if Neo4j::Transaction.running? + Neo4j.stop + delete_db + + reset_config end diff --git a/test/neo4j/transaction_spec.rb b/test/neo4j/transaction_spec.rb index eb3f1cf51..3fe1a77dc 100644 --- a/test/neo4j/transaction_spec.rb +++ b/test/neo4j/transaction_spec.rb @@ -32,15 +32,20 @@ class BaseNode #end describe "transaction rollback" do - before(:all) do start end - after(:all) do stop end + before(:all) do + start + end + after(:all) do + stop + end it "should not change properties" do - node = Neo4j::Transaction.run { BaseNode.new {|n| n.foo = 'foo'} } + node = Neo4j::Transaction.run { b = BaseNode.new; b.foo = 'foo'; b } # when doing a rollback Neo4j::Transaction.run { |t| node.foo = "changed" + node.foo.should == "changed" t.failure } @@ -65,10 +70,12 @@ class BaseNode it "should load node using its id" do - node = BaseNode.new {|n| - n.baaz = "hello" + node = nil + Neo4j::Transaction.run { + node = BaseNode.new + node.baaz = "hello" } - + Neo4j.stop Neo4j.start diff --git a/test/neo4j/tx_tracker_spec.rb b/test/neo4j/tx_tracker_spec.rb index 80e777688..35f9be0e1 100644 --- a/test/neo4j/tx_tracker_spec.rb +++ b/test/neo4j/tx_tracker_spec.rb @@ -3,7 +3,7 @@ require 'neo4j' require 'neo4j/spec_helper' -require 'extensions/tx_tracker' +require 'neo4j/extensions/tx_tracker' class TxTestNode @@ -16,29 +16,62 @@ def to_s end end + +describe "TxTracker (TxNodeList)" do + it "should set property 'tx_finished' on the last TxNode that was commited" do + stop + Neo4j.load_tx_tracker + Neo4j.start + @tx_node_list = Neo4j::TxNodeList.instance + + Neo4j::Transaction.run do + TxTestNode.new.myid = '1' + TxTestNode.new.myid = '2' + TxTestNode.new.myid = '3' + end + + Neo4j::Transaction.run do + first = @tx_node_list.tx_nodes.first + first[:tx_finished].should == true + + second = @tx_node_list.tx_nodes.to_a[1] + second[:tx_finished].should be_nil + + third = @tx_node_list.tx_nodes.to_a[2] + third[:tx_finished].should be_nil + end + stop + end + +end + describe "TxTracker (TxNodeList)" do before(:all) do - Neo4j::Config[:track_tx] = true + Neo4j.start + Neo4j.load_tx_tracker + Neo4j::Transaction.new + @tx_node_list = Neo4j::TxNodeList.instance end before(:each) do - stop - start - @tx_node_list = Neo4j::TxNodeList.instance + Neo4j::Transaction.new + end + + after(:each) do + Neo4j::Transaction.finish end after(:all) do stop - Neo4j::Config[:track_tx] = false # it is only this this spec that tests the TxTracker extension - remove it Neo4j.event_handler.remove(Neo4j::TxNodeList) end + it "should have a reference to the TxNodeList" do - puts "@tx_node_list= #{@tx_node_list.inspect}" @tx_node_list.should_not be_nil end @@ -63,22 +96,6 @@ def to_s end - it "should set property 'tx_finished' on the last TxNode that was commited" do - Neo4j::Transaction.run do - TxTestNode.new.myid = '1' - TxTestNode.new.myid = '2' - TxTestNode.new.myid = '3' - end - first = @tx_node_list.tx_nodes.first - first[:tx_finished].should == true - - second = @tx_node_list.tx_nodes.to_a[1] - second[:tx_finished].should be_nil - - third = @tx_node_list.tx_nodes.to_a[2] - third[:tx_finished].should be_nil - end - it "should set property 'property_changed' when a node property is changed" do a = TxTestNode.new a.myid = "hej" @@ -122,7 +139,9 @@ def to_s # when Neo4j.load(id).should_not be_nil Neo4j.undo_tx + Neo4j::Transaction.finish + Neo4j::Transaction.new # then Neo4j.load(id).should be_nil end @@ -134,11 +153,17 @@ def to_s Neo4j.load(id).should_not be_nil a.delete + Neo4j::Transaction.finish + + Neo4j::Transaction.new Neo4j.load(id).should be_nil # when Neo4j.undo_tx + Neo4j::Transaction.finish + + Neo4j::Transaction.new # then Neo4j.load(id).should be_nil end diff --git a/test/neo4j/value_object_spec.rb b/test/neo4j/value_object_spec.rb index a0f3d20fa..d57c7d5a8 100644 --- a/test/neo4j/value_object_spec.rb +++ b/test/neo4j/value_object_spec.rb @@ -15,8 +15,8 @@ class FooBarNode describe 'ValueObjects' do - before(:all) { start } - after(:all) { stop } + before(:all) { start; Neo4j::Transaction.new } + after(:all) { stop; Neo4j::Transaction.finish } it "should value object created with new param should be anew record" do