Skip to content

Commit

Permalink
Fixed so that the classname property is not required when reading fro…
Browse files Browse the repository at this point in the history
…m a neo4j database. That means that we can read a neo4j database that was created by the Java Neo4j. [#63 state:resolved]
  • Loading branch information
andreas committed Aug 5, 2009
1 parent ef85962 commit d7a784e
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 26 deletions.
12 changes: 7 additions & 5 deletions README.rdoc
Expand Up @@ -811,7 +811,7 @@ be used for both traversing and adding new objects to a specific relationship ty
For example, let say that Person can have a relationship to any other node class with the type 'friends':

class Person
include Neo::Node
include Neo4j::Node
has_n :knows # will generate a knows method for outgoing relationships
end

Expand All @@ -832,7 +832,7 @@ If you want to express that the relationship should point to a specific class
use the 'to' method on the has_n method.

class Person
include Neo::Node
include Neo4j::Node
has_n(:knows).to(Person)
end

Expand All @@ -841,7 +841,7 @@ It is also possible to generate methods for incoming relationships by using the

Example:
class Person
include Neo::Node
include Neo4j::Node
has_n :knows # will generate a knows method for outgoing relationships
has_n(:known_by).from(:knows) # will generate a known_by method for incomming knows relationship
end
Expand Down Expand Up @@ -1379,9 +1379,11 @@ Neo4j supports full text search by setting the tokenized property to true on an

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.
If this classname property does not exist it will use the default Neo4j::Node for nodes and
Neo4j::Relationships::Relationship for relationship.

class Person
include Neo::Node
class Person
include Neo4j::Node

def hello
end
Expand Down
8 changes: 2 additions & 6 deletions lib/neo4j/mixins/node.rb
Expand Up @@ -45,7 +45,6 @@ def initialize(*args)
# :api: private
def init_with_node(node)
@internal_node = node
self.classname = self.class.to_s unless @internal_node.hasProperty("classname")
$NEO_LOGGER.debug {"loading node '#{self.class.to_s}' node id #{@internal_node.getId()}"}
end

Expand All @@ -63,9 +62,6 @@ def init_without_node
# Sets a neo property on this node. This property does not have to be declared first.
# If the value of the property is nil the property will be removed.
#
# Runs in a new transaction if there is not one already running,
# otherwise it will run in the existing transaction.
#
# ==== Parameters
# name<String>:: the name of the property to be set
# value<Object>:: the value of the property to be set.
Expand Down Expand Up @@ -97,7 +93,8 @@ def set_property(name, value)
end


# Sets the given property to a given value
# Sets the given property to a given value.
# Same as Neo4j::NodeMixin#set_property
#
# :api: public
def []=(name, value)
Expand Down Expand Up @@ -132,7 +129,6 @@ def remove_property(name)
# :api: public
def get_property(name)
$NEO_LOGGER.debug{"get property '#{name}'"}

return nil if ! property?(name)
value = @internal_node.get_property(name.to_s)
if self.class.marshal?(name)
Expand Down
50 changes: 44 additions & 6 deletions lib/neo4j/mixins/relationship.rb
Expand Up @@ -7,7 +7,7 @@ module Neo4j
module RelationshipMixin
extend TransactionalMixin

attr_reader :internal_r
attr_reader :internal_r

# Initialize the Relationship object with specified java org.neo4j.api.core.Relationship object
# Expects at least one parameter.
Expand Down Expand Up @@ -65,7 +65,7 @@ def relationship_type
end


# Deletes the relationship between two nodes.
# Deletes this relationship.
#
# :api: public
def delete
Expand All @@ -78,19 +78,55 @@ def delete
end_node.class.indexer.on_relationship_deleted(end_node, type) unless end_node.nil?
end


# Sets a neo property on this relationship. This property does not have to be declared first.
# If the value of the property is nil the property will be removed.
#
# ==== Parameters
# name<String>:: the name of the property to be set
# value<Object>:: the value of the property to be set.
#
# :api: public
def set_property(key, value)
@internal_r.setProperty(key, value)
if value.nil?
remove_property(key)
else
@internal_r.setProperty(key, value)
end
end

# Checks if the given neo property exists.
#
# ==== Returns
# true if the property exists
#
# :api: public
def property?(key)
@internal_r.hasProperty(key)
end

# Returns the value of the given neo property.
#
# ==== Returns
# the value of the property or nil if the property does not exist
#
# :api: public
def get_property(key)
return nil unless self.property?(key)
@internal_r.getProperty(key)
end

# Removes the property from this relationship
# For more information see JavaDoc PropertyContainer#removeProperty
#
# ==== Returns
# true if the property was removed, false otherwise
#
# :api: public
def remove_property(name)
!@internal_r.removeProperty(name).nil?
end

# Returns a hash of all properties.
#
# ==== Returns
Expand All @@ -107,20 +143,22 @@ def props
ret
end

# Returns the given property
# Returns the given property
# Same as #get_property
#
# :api: public
def [](name)
get_property(name.to_s)
end

# Sets the given property to a given value
# Same as #set_property
#
# :api: public
def []=(name, value)
set_property(name.to_s, value)
end

def classname
get_property('classname')
end
Expand Down Expand Up @@ -167,7 +205,7 @@ def ==(o)
def hash
internal_node.hashCode
end

transactional :initialize, :property?, :set_property, :get_property, :delete

#
Expand Down
15 changes: 6 additions & 9 deletions lib/neo4j/neo.rb
Expand Up @@ -121,7 +121,7 @@ def self.number_of_ids_in_use
end

def self.number_of_properties_in_use
self.number_of_ids_in_use - self.number_of_relationships_in_use - self.number_of_nodes_in_use + 1
self.number_of_ids_in_use - self.number_of_relationships_in_use - self.number_of_nodes_in_use + 2
end

# Prints some info about the database
Expand Down Expand Up @@ -203,23 +203,20 @@ def find_relationship(id)


# Loads a Neo node
# Expects the neo property 'classname' to exist.
# That property is used to load the ruby instance
# If the neo property 'classname' does not exist then it will map the neo node to the ruby class Neo4j::Node
#
# :api: private
def load_node(neo_node)
return nil unless neo_node.has_property('classname')
_load neo_node.get_property('classname'), neo_node
classname = neo_node.has_property('classname') ? neo_node.get_property('classname') : Neo4j::Node.to_s
_load classname, neo_node
end


# Loads a Neo relationship
# If the neo property 'classname' to exist it will use that to create an instance of that class.
# Otherwise it will create an instance of Neo4j::Relationships::Relationship that represent 'rel'
# If the neo property 'classname' it will create a ruby object of that type otherwise it create an Ruby object of class Neo4j::Relationships::Relationship
#
def load_relationship(rel)
classname = rel.get_property('classname') if rel.has_property('classname')
classname = Neo4j::Relationships::Relationship.to_s if classname.nil?
classname = rel.has_property('classname') ? rel.get_property('classname') : Neo4j::Relationships::Relationship.to_s
_load classname, rel
end

Expand Down
38 changes: 38 additions & 0 deletions test/neo4j/neo_spec.rb
Expand Up @@ -180,4 +180,42 @@ class TestNode
end
end

it "should load a node even if it does not have a classname property" do
Neo4j::Transaction.run do
n = Neo4j::Node.new
id = n.neo_node_id
Neo4j.load(id).should_not be_nil

# when classname property does not exist
n[:classname] = nil

# then it should be possible to load it again, default should be Neo4j::Node class
node = Neo4j.load(id)
node.should_not be_nil
node.should be_kind_of(Neo4j::Node)
end

end


it "should load a relationship even if it does not have a classname property" do
Neo4j::Transaction.run do
n1 = Neo4j::Node.new
n2 = Neo4j::Node.new
n1.relationships.outgoing(:foobaar) << n2
r = n1.relationships.outgoing(:foobaar).first
id = r.neo_relationship_id
Neo4j.load_relationship(id).should_not be_nil

# when classname property does not exist
r[:classname] = nil

# then it should be possible to load it again, default should be Neo4j::Node class
rel = Neo4j.load_relationship(id)
rel.should_not be_nil
rel.should be_kind_of(Neo4j::Relationships::Relationship)
end

end

end

0 comments on commit d7a784e

Please sign in to comment.