diff --git a/README b/README index a66d138bf..1261bf01a 100644 --- a/README +++ b/README @@ -83,4 +83,20 @@ Traversing relationships: Note that the bars method returns an object that mixins the Enumeration module. +=== Unmarshalling + +The neo module will automatically unmarshalling nodes to the correct ruby class. +It does this by reading the classname property and loading that ruby class with that node. + + class Foo << Neo::Node + def hello + end + end + + f1 = Foo.new {} + + # load the class again + f2 = Neo::neo_service.find_node(foo.neo_node_id) + f2.hello + # f2.class == Foo diff --git a/lib/neo.rb b/lib/neo.rb index 1d6283d7a..484fa55da 100644 --- a/lib/neo.rb +++ b/lib/neo.rb @@ -1,16 +1,40 @@ require 'neo/java_libs' require 'neo/neo_service' require 'neo/node' +require 'logger' module Neo + + # + # Set logger used by Neo + $neo_logger = Logger.new(STDOUT) + $neo_logger.level = Logger::WARN + - # # Runs a block in a Neo transaction # - # All CRUD operations must be run in a transaction - # If a block is given then that block will be executed in a transaction, - # otherwise it will simply return a java neo transaction object. + # Most operations on neo requires an transaction. + # include 'neo' + # + # Neo::transaction { + # node = Neo.new + # } + # + # You have also access to transaction object + # + # Neo::transaction { |t| + # # something failed + # t.failure # will cause a rollback + # } + # + # + # If a block is not given than the transaction method will return a transaction object. + # + # transaction = Neo::transaction + # transaction.begin + # etc ... + # # def transaction return Transaction unless block_given? diff --git a/lib/neo/neo_service.rb b/lib/neo/neo_service.rb index 96ce08dcd..58ef333cd 100644 --- a/lib/neo/neo_service.rb +++ b/lib/neo/neo_service.rb @@ -21,7 +21,6 @@ class NeoService # def start(storage = "var/neo") raise Exception.new("Already started neo") if @neo - puts "start neo" @neo = EmbeddedNeo.new(storage) ref_node = nil @@ -29,6 +28,9 @@ def start(storage = "var/neo") ref_node = @neo.getReferenceNode @meta_nodes = MetaNodes.new(ref_node) end + + $neo_logger.info{ "Started neo. DB at '#{storage}'"} + end @@ -50,7 +52,7 @@ def find_meta_node(classname) # Returns a Node object that has the given id or nil # def find_node(id) - neo_node = @neo.findNodeById(id) + neo_node = @neo.getNodeById(id) load_node(neo_node) end @@ -69,7 +71,7 @@ def load_node(neo_node) # Must be done before the program stops # def stop - puts "stop neo #{@neo}" + $neo_logger.info {"stop neo #{@neo}"} @neo.shutdown @neo = nil end diff --git a/lib/neo/node.rb b/lib/neo/node.rb index ae45908ab..cda876db2 100644 --- a/lib/neo/node.rb +++ b/lib/neo/node.rb @@ -71,10 +71,17 @@ def neo_node_id def to_s iter = @internal_node.getPropertyKeys.iterator - s = self.class.to_s + ", properties:\n" - while (iter.hasNext) do - p = iter.next - s << "'#{p}' = '#{@internal_node.getProperty(p)}'\n" + s = self.class.to_s + if !iter.hasNext + s << " no properties" + else + s << " Properties: [" + while (iter.hasNext) do + p = iter.next + s << "['#{p}' = '#{@internal_node.getProperty(p)}']" + s << ', ' if iter.hasNext + end + s << "]" end s end diff --git a/test/neo_spec.rb b/test/neo_spec.rb index e95688c16..27a39281d 100644 --- a/test/neo_spec.rb +++ b/test/neo_spec.rb @@ -22,9 +22,14 @@ def stop # the following specs are not always run inside ONE Neo transaction # -describe "When using several transactions" do +describe "When neo has been restarted" do - describe Neo::MetaNode do + def restart + Neo::neo_service.stop + Neo::neo_service.start DB_LOCATION + end + + describe Neo::NeoService do before(:all) do start end @@ -33,9 +38,38 @@ def stop stop end - it "should find all instances of a class" + it "should contain referenses to all meta nodes" do + # given + Neo::transaction { + metas = Neo::neo_service.meta_nodes.nodes + metas.to_a.size.should == 0 + } + + class Foo < Neo::Node + end + + + Neo::transaction { + metas = Neo::neo_service.meta_nodes.nodes + metas.to_a.size.should == 1 + } + + # when + restart + + # then + Neo::transaction { + metas = Neo::neo_service.meta_nodes.nodes + metas.to_a.size.should == 1 + meta = Neo::neo_service.find_meta_node('Foo') + meta.should_not be_nil + meta.meta_classname.should == "Foo" + } + + + end - it "should be unique, when neo is restarted" do + it "should have unique node ids for the Meta Node" do # when Neo is restarted make sure that the node representing the class # has the same node_id @@ -47,15 +81,28 @@ class Foo < Neo::Node id1 = Neo::neo_service.find_meta_node('Foo').neo_node_id } - Neo::neo_service.stop - Neo::neo_service.start DB_LOCATION - + restart + id2 = nil Neo::transaction { id2 = Neo::neo_service.find_meta_node('Foo').neo_node_id } id1.should == id2 end + + it "should load node using its id" do + node = Neo::Node.new {|n| + n.baaz = "hello" + } + + Neo::neo_service.stop + Neo::neo_service.start DB_LOCATION + + Neo::transaction { + node2 = Neo::neo_service.find_node(node.neo_node_id) + node.baaz.should == "hello" + } + end end end @@ -63,7 +110,7 @@ class Foo < Neo::Node # the following specs are run inside one Neo transaction # -describe "When using one transactions" do +describe "When running in one transaction" do before(:all) do start end @@ -134,19 +181,19 @@ class Kalle < Neo::Node it "should have a unique (neo) id" do - n1 = Neo::Node.new{} + n1 = Neo::Node.new n1.neo_node_id.should be_kind_of(Fixnum) end it "should know the name of the ruby class it represent" do - node1 = Neo::Node.new { } + node1 = Neo::Node.new node1.classname.should be == "Neo::Node" class FooBar < Neo::Node end - node2 = FooBar.new {} + node2 = FooBar.new node2.classname.should be == "FooBar" end