Skip to content

Commit

Permalink
impl pending specs for traversal of any depth, added RDocs [#13]
Browse files Browse the repository at this point in the history
  • Loading branch information
andreasronge committed Dec 28, 2008
1 parent 0fa3422 commit c0556d9
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 25 deletions.
15 changes: 14 additions & 1 deletion README.rdoc
Expand Up @@ -142,6 +142,10 @@ Traversing using a filter

person.friends{ salary == 10000 }.each {|n| ...}

Traversing with a specific depth (depth 1 is default)

person.friends{ salary == 10000}.depth(3).each { ... }

Deleting a relationship

person.relations[person2].delete
Expand Down Expand Up @@ -661,10 +665,19 @@ Each type of relationship has a method that returns an Enumerable object that en
to traverse that type of relationship.

For example the Person example above declares one relationship of type friends.
You can traverse all Person's friend by doing:
You can traverse all Person's friend by doing of depth 1:

f.friends.each { |n| puts n }

Traversing friends of a specific depth.
Example finding all friends and friends friends.

f.friends.depth(2).each { ...}

Traversing to the end of the graph

f.friends.depth(:all).each { ...}

=== Filtering nodes in a relationship

If you want to find one node in a relationship you can use a filter.
Expand Down
31 changes: 15 additions & 16 deletions lib/neo4j/relations/has_n_relations.rb
Expand Up @@ -14,7 +14,7 @@ def initialize(node, type, &filter)
@node = node
@type = RelationshipType.instance(type)
@filter = filter
@depth = 1
@stop_evaluator = DepthStopEvaluator.new(1)
@info = node.class.relations_info[type.to_sym]

if @info[:outgoing]
Expand All @@ -41,14 +41,17 @@ def initialize(node, type, &filter)
#
# :api: public
def depth(d)
@depth = d
if d == :all
@stop_evaluator = org.neo4j.api.core.StopEvaluator::END_OF_GRAPH
else
@stop_evaluator = DepthStopEvaluator.new(d)
end
self
end

def each
stop = DepthStopEvaluator.new(@depth)
traverser = @node.internal_node.traverse(org.neo4j.api.core.Traverser::Order::BREADTH_FIRST,
stop,
@stop_evaluator,
org.neo4j.api.core.ReturnableEvaluator::ALL_BUT_START_NODE,
@type,
@direction)
Expand All @@ -65,7 +68,7 @@ def each
end
end

#

# Creates a relationship instance between this and the other node.
# If a class for the relationship has not been specified it will be of type DynamicRelation.
# To set a relationship type see #Neo4j::relations
Expand All @@ -81,10 +84,10 @@ def new(other)
end


#
# Creates a relationship between this and the other node.
# Returns self so that we can add several nodes like this:
#
# ==== Example
#
# n1 = Node.new # Node has declared having a friend type of relationship
# n2 = Node.new
# n3 = NodeMixin.new
Expand All @@ -96,6 +99,10 @@ def new(other)
# n1.friends.new(n2)
# n1.friends.new(n3)
#
# ==== Returns
# self
#
# :api: public
def <<(other)
from, to = @node, other
from,to = to,from unless @info[:outgoing]
Expand All @@ -108,23 +115,15 @@ def <<(other)
end


#
# Private class
#
# :api: private
class DepthStopEvaluator
include org.neo4j.api.core.StopEvaluator

def initialize(depth)
# puts "DEPTH = #{depth} #{depth.class.to_s}"
@depth = depth
end

# def self.new(depth)
# if depth.to_sym == :all
# return org.neo4j.api.core.StopEvaluator::END_OF_GRAPH
# end
# super depth
# end

def isStopNode(pos)
pos.depth >= @depth
Expand Down
31 changes: 23 additions & 8 deletions test/neo4j/relation_spec.rb
Expand Up @@ -192,13 +192,14 @@ class TestNode
end
end

describe "traversing nodes of any depth" do
describe "#relations, traversing nodes of a specific depth" do
before(:all) do
undefine_class :PersonNode
class PersonNode
include Neo4j::NodeMixin
property :name
has_n :friends
has_n(:known_by).from(PersonNode, :friends)
end

@n0 = PersonNode.new
Expand All @@ -214,36 +215,50 @@ class PersonNode
@n112.friends << @n1121
end

it "should be possible with node.friends.depth(2).each" do
it "should be possible 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)
end

it "should be possible with node.friends.depth(3).each" do
it "should be possible 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)
end

it "should be possible with node.friends.depth(:all).each" do
pending
it "should be possible 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)
end

it "should get all nodes two levels deep (for levels(2))" do
it "should be possible with incoming nodes of depth 2" do
nodes = @n1.known_by.depth(2)
nodes.should include(@n0)
nodes.to_a.size.should == 1

nodes = @n11.known_by.depth(2)
nodes.should include(@n0, @n1)
nodes.to_a.size.should == 2

nodes = @n112.known_by.depth(2)
nodes.should include(@n1, @n11)
nodes.to_a.size.should == 2
end


it "should get all nodes two levels deep (for depth(2))" do
pending
nodes = @n1.relations.outgoing(:friends).levels(2)
nodes = @n1.relations.outgoing(:friends).depth(2)
@n1.friends.levels
nodes.should include(@n11,@n12,@n112)
nodes.should_not include(@n0,@n1,@n1121)
end

it "should get all nodes (for levels(:all))" do
pending
nodes = @n1.relations.outgoing(:friends).levels(:all)
nodes = @n1.relations.outgoing(:friends).depth(:all)
nodes.should include(@n11,@n12,@n112,@n1121)
nodes.should_not include(@n0,@n1)
end
Expand Down

0 comments on commit c0556d9

Please sign in to comment.