neography 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- neography (0.0.3)
4
+ neography (0.0.4)
5
5
  httparty (~> 0.6.1)
6
6
  json
7
7
 
@@ -13,6 +13,7 @@ GEM
13
13
  fakeweb (1.3.0)
14
14
  httparty (0.6.1)
15
15
  crack (= 0.1.8)
16
+ json (1.4.6)
16
17
  json (1.4.6-java)
17
18
  net-http-spy (0.2.1)
18
19
  rspec (2.0.1)
@@ -28,6 +29,7 @@ GEM
28
29
 
29
30
  PLATFORMS
30
31
  java
32
+ ruby
31
33
 
32
34
  DEPENDENCIES
33
35
  fakeweb (~> 1.3.0)
data/README.rdoc CHANGED
@@ -35,12 +35,12 @@ Just add gem 'neography' to your Gemfile and run bundle install
35
35
 
36
36
  A thin ruby wrapper Neography::Rest which tries to mirror the Neo4j Rest API and returns JSON or Nil:
37
37
 
38
- # protocol, server, port, log_file, log_enabled
39
- @neo = Neography::Rest.new ('http://', '192.168.10.1', 7479, 'log/neography.log', true)
38
+ # protocol, server, port, log_file, log_enabled, max_threads
39
+ @neo = Neography::Rest.new ('http://', '192.168.10.1', 7479, 'log/neography.log', true, 50)
40
40
 
41
41
  Default Parameters are:
42
42
 
43
- @neo = Neography::Rest.new ('http://', 'localhost', 7474, '/neography.log', false)
43
+ @neo = Neography::Rest.new ('http://', 'localhost', 7474, '/neography.log', false, 20)
44
44
 
45
45
  To Use:
46
46
 
@@ -104,6 +104,72 @@ To Use:
104
104
 
105
105
  Please see the specs for more examples.
106
106
 
107
+ Experimental:
108
+
109
+ nodes = @neo.create_nodes(5) # Create 5 empty nodes
110
+ nodes = @neo.create_nodes_threaded(5) # Create 5 empty nodes using threads
111
+ nodes = @neo.create_node_nodes([{"age" => 31, "name" => "Max"},
112
+ {"age" => 24, "name" => "Alex"}) # Create two nodes with properties
113
+ nodes = @neo.create_node_nodes_threaded([{"age" => 31, "name" => "Max"},
114
+ {"age" => 24, "name" => "Alex"}) # Create two nodes with properties threaded
115
+ nodes = @neo.get_nodes([17,86,397,33]) # Get four nodes by their id
116
+
117
+ one_set_nodes = @neo.create_nodes(3)
118
+ another_node = @neo.create_node("age" => 31, "name" => "Max")
119
+ nodes = @neo.get_nodes([one_set_nodes, another_node]) # Get four nodes
120
+
121
+ === Phase 2 (work in progress):
122
+
123
+ Trying to mimic the Neo4j.rb API.
124
+
125
+ Now we are returning full objects. The properties of the node or relationship can be accessed directly (node.name).
126
+ The Neo4j ID is available by using node.neo_id .
127
+
128
+ @neo2 = Neography::Rest.new ('http://', '192.168.10.1')
129
+
130
+ Neography::Node.create # Create an empty node
131
+ Neography::Node.create("age" => 31, "name" => "Max") # Create a node with some properties
132
+ Neography::Node.create(@neo2, {"age" => 31, "name" => "Max"}) # Create a node on the server defined in @neo2
133
+ Neography::Node.create({"age" => 31, "name" => "Max"}, @neo2) # Same as above, but different order
134
+
135
+ Neography::Node.load(5) # Get a node and its properties by id
136
+ Neography::Node.load(existing_node) # Get a node and its properties by Node
137
+ Neography::Node.load("http://localhost:7474/db/data/node/2") # Get a node and its properties by String
138
+
139
+ Neography::Node.load(@neo2, 5) # Get a node on the server defined in @neo2
140
+ Neography::Node.load(5, @neo2) # Same as above, but different order
141
+
142
+ n1 = Node.create
143
+ n1.del # Deletes the node
144
+ n1.exist? # returns true/false if node exists in Neo4j
145
+
146
+ n1 = Node.create("age" => 31, "name" => "Max")
147
+ n1[:age] #returns 31 # Get a node property using [:key]
148
+ n1.name #returns "Max" # Get a node property as a method
149
+ n1[:age] = 24 # Set a node property using [:key] =
150
+ n1.name = "Alex" # Set a node property as a method
151
+ n1[:hair] = "black" # Add a node property using [:key] =
152
+ n1.weight = 190 # Add a node property as a method
153
+ n1[:name] = nil # Delete a node property using [:key] = nil
154
+ n1.name = nil # Delete a node property by setting it to nil
155
+
156
+ n2 = Neography::Node.create
157
+ new_rel = Neography::Relationship.create(:family, n1, n2) # Create a relationship from my_node to node2
158
+ new_rel.start_node # Get the start/from node of a relationship
159
+ new_rel.end_node # Get the end/to node of a relationship
160
+ existing_rel = Neography::Relationship.load(12) # Get an existing relationship by id
161
+ existing_rel.del # Delete a relationship
162
+
163
+ Neography::Relationship.create(:friends, n1, n2)
164
+ n1.rel?(:friends) # Has a friends relationship
165
+ n1.rel?(:outgoing, :friends) # Has outgoing friends relationship
166
+ n1.rel?(:friends, :outgoing) # same, just the other way
167
+ n1.rel?(:outgoing) # Has any outgoing relationships
168
+ n1.rel?(:both) # Has any relationships
169
+ n1.rel?(:all) # same as above
170
+ n1.rel? # same as above
171
+
172
+
107
173
  See Neo4j API for:
108
174
  * {Order}[http://components.neo4j.org/neo4j-examples/1.2.M04/apidocs/org/neo4j/graphdb/Traverser.Order.html]
109
175
  * {Uniqueness}[http://components.neo4j.org/neo4j-examples/1.2.M04/apidocs/org/neo4j/kernel/Uniqueness.html]
@@ -0,0 +1,14 @@
1
+ module Neography
2
+ class Config
3
+ class << self; attr_accessor :protocol, :server, :port, :log_file, :log_enabled, :logger, :max_threads end
4
+
5
+ @protocol = 'http://'
6
+ @server = 'localhost'
7
+ @port = 7474
8
+ @log_file = 'neography.log'
9
+ @log_enabled = false
10
+ @logger = Logger.new(@log_file) if @log_enabled
11
+ @max_threads = 20
12
+
13
+ end
14
+ end
@@ -0,0 +1,21 @@
1
+ module Neography
2
+
3
+ # == This mixin is used for both nodes and relationships to decide if two entities are equal or not.
4
+ #
5
+ module Equal
6
+ def equal?(o)
7
+ eql?(o)
8
+ end
9
+
10
+ def eql?(o)
11
+ return false unless o.respond_to?(:neo_id)
12
+ o.neo_id == neo_id
13
+ end
14
+
15
+ def ==(o)
16
+ eql?(o)
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,10 @@
1
+ module Neography
2
+
3
+ class << self
4
+
5
+ def ref_node(this_db = Neography::Rest.new)
6
+ this_db.get_root
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,43 @@
1
+ module Neography
2
+ class Node < PropertyContainer
3
+ include Neography::NodeRelationship
4
+ include Neography::Equal
5
+ include Neography::Property
6
+
7
+ attr_accessor :neo_server
8
+
9
+ class << self
10
+ def create(*args)
11
+ # the arguments can be an hash of properties to set or a rest instance
12
+ props = (args[0].respond_to?(:each_pair) && args[0]) || args[1]
13
+ db = (args[0].is_a?(Neography::Rest) && args[0]) || args[1] || Neography::Rest.new
14
+ node = Neography::Node.new(db.create_node(props))
15
+ node.neo_server = db
16
+ node
17
+ end
18
+
19
+ def load(*args)
20
+ # the first argument can be an hash of properties to set
21
+ node = !args[0].is_a?(Neography::Rest) && args[0] || args[1]
22
+
23
+ # a db instance can be given, it is the first argument or the second
24
+ db = (args[0].is_a?(Neography::Rest) && args[0]) || args[1] || Neography::Rest.new
25
+ node = db.get_node(node)
26
+ node = Neography::Node.new(node) unless node.nil?
27
+ node.neo_server = db unless node.nil?
28
+ node
29
+ end
30
+
31
+ #alias_method :new, :create
32
+ end
33
+
34
+ def del
35
+ self.neo_server.delete_node!(self.neo_id)
36
+ end
37
+
38
+ def exist?
39
+ !self.neo_server.get_node(self.neo_id).nil?
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,45 @@
1
+ module Neography
2
+ module NodeRelationship
3
+
4
+ def outgoing(types=nil)
5
+ if types
6
+ NodeTraverser.new(self).outgoing(types)
7
+ else
8
+ NodeTraverser.new(self).outgoing
9
+ end
10
+ end
11
+
12
+ def incoming(types=nil)
13
+ if types
14
+ NodeTraverser.new(self).incoming(types)
15
+ else
16
+ NodeTraverser.new(self).incoming
17
+ end
18
+ end
19
+
20
+ def both(types=nil)
21
+ if types
22
+ NodeTraverser.new(self).both(types)
23
+ else
24
+ NodeTraverser.new(self) # default is both
25
+ end
26
+ end
27
+
28
+ def rels(*types)
29
+ Neography::RelationshipTraverser.new(self, types, :both)
30
+ end
31
+
32
+ def rel(dir, type)
33
+ Neography::RelationshipTraverser.new(self, type, dir).first
34
+ end
35
+
36
+ def rel?(dir=nil, type=nil)
37
+ if DIRECTIONS.include?(dir.to_s)
38
+ !self.neo_server.get_node_relationships(self, dir, type).nil?
39
+ else
40
+ !self.neo_server.get_node_relationships(self, type, dir).nil?
41
+ end
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,23 @@
1
+ module Neography
2
+ class NodeTraverser
3
+ include Enumerable
4
+
5
+ attr_accessor :order, :uniqueness, :depth, :prune, :filter
6
+
7
+ def initialize(from, types = nil, dir=nil)
8
+ @from = from
9
+ @depth = 1
10
+ @order = "depth first"
11
+ @uniqueness = "none"
12
+ if types.nil? || dir.nil?
13
+ # @td = org.neo4j.kernel.impl.traversal.TraversalDescriptionImpl.new.breadth_first()
14
+ else
15
+ # @types = type_to_java(type)
16
+ # @dir = dir_to_java(dir)
17
+ # @td = org.neo4j.kernel.impl.traversal.TraversalDescriptionImpl.new.breadth_first().relationships(@type, @dir)
18
+ end
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,55 @@
1
+ module Neography
2
+ module Property
3
+
4
+
5
+ def [](key)
6
+ return unless respond_to?(key)
7
+ @table[key]
8
+ end
9
+
10
+ def []=(key, value)
11
+ k = key.to_s
12
+ if value.nil?
13
+ if self.is_a? Neography::Node
14
+ neo_server.remove_node_properties(self.neo_id, [key])
15
+ @table[key] = nil
16
+ else
17
+ neo_server.remove_relationship_properties(self.neo_id, [key])
18
+ @table[key] = nil
19
+ end
20
+ else
21
+ if self.is_a? Neography::Node
22
+ neo_server.set_node_properties(self.neo_id, {k => value})
23
+ else
24
+ neo_server.set_relationship_properties(self.neo_id, {k => value})
25
+ end
26
+
27
+ new_ostruct_member(k) unless self.respond_to?(key)
28
+
29
+ end
30
+ end
31
+
32
+
33
+ def new_ostruct_member(name)
34
+ name = name.to_sym
35
+ unless self.respond_to?(name)
36
+ meta = class << self; self; end
37
+ meta.send(:define_method, name) { @table[name] }
38
+ meta.send(:define_method, "#{name}=") do |x|
39
+ @table[name] = x
40
+ self[name.to_sym] = x
41
+ end
42
+ end
43
+ end
44
+
45
+
46
+ def self.method_missing(method_sym, *arguments, &block)
47
+ if (method_sym.to_s =~ /$=/) != nil
48
+ new_ostruct_member(method_sym.to_s.chomp("="))
49
+ else
50
+ super
51
+ end
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,17 @@
1
+ module Neography
2
+ class PropertyContainer < OpenStruct
3
+ attr_reader :neo_id
4
+
5
+ def initialize(hash=nil)
6
+ @table = {}
7
+ if hash
8
+ @neo_id = hash["self"].split('/').last
9
+ for k,v in hash["data"]
10
+ @table[k.to_sym] = v
11
+ new_ostruct_member(k)
12
+ end
13
+ end
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,54 @@
1
+ module Neography
2
+ class Relationship < PropertyContainer
3
+ include Neography::Equal
4
+ include Neography::Property
5
+
6
+ attr_accessor :start_node, :end_node, :rel_type
7
+
8
+ class << self
9
+
10
+ def create(type, from_node, to_node, props=nil)
11
+ rel = Neography::Relationship.new(from_node.neo_server.create_relationship(type, from_node, to_node, props))
12
+ rel.start_node = from_node
13
+ rel.end_node = to_node
14
+ rel.rel_type = type
15
+ rel
16
+ end
17
+
18
+ def load(*args)
19
+ # the first argument can be an hash of properties to set
20
+ rel = !args[0].is_a?(Neography::Rest) && args[0] || args[1]
21
+
22
+ # a db instance can be given, it is the first argument or the second
23
+ db = (args[0].is_a?(Neography::Rest) && args[0]) || args[1] || Neography::Rest.new
24
+ rel = db.get_relationship(rel)
25
+ unless rel.nil?
26
+ rel = Neography::Relationship.new(rel)
27
+ rel.start_node = Neography::Node.load(rel.start_node)
28
+ rel.end_node = Neography::Node.load(rel.end_node)
29
+ end
30
+ rel
31
+ end
32
+ end
33
+
34
+ def initialize(hash=nil, neo_server=nil)
35
+ super(hash)
36
+ @start_node = hash["start"].split('/').last
37
+ @end_node = hash["end"].split('/').last
38
+ @rel_type = hash["type"]
39
+ end
40
+
41
+ def del
42
+ self.start_node.neo_server.delete_relationship(self.neo_id)
43
+ end
44
+
45
+ def other_node(node)
46
+ if node = @start_node
47
+ @end_node
48
+ else
49
+ @start_node
50
+ end
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,59 @@
1
+ module Neography
2
+ class RelationshipTraverser
3
+ include Enumerable
4
+
5
+ def initialize(node, types, direction)
6
+ @node = node
7
+ @types = [types]
8
+ @direction = direction
9
+ end
10
+
11
+ def to_s
12
+ if @types.size == 1 && !@types.empty?
13
+ "#{self.class} [type: #{@type} dir:#{@direction}]"
14
+ elsif !@types.empty?
15
+ "#{self.class} [types: #{@types.join(',')} dir:#{@direction}]"
16
+ else
17
+ "#{self.class} [types: ANY dir:#{@direction}]"
18
+ end
19
+ end
20
+
21
+ def each
22
+ iterator.each { |i| yield Neography::Relationship.new(i, @node.neo_server) }
23
+ end
24
+
25
+ def empty?
26
+ first == nil
27
+ end
28
+
29
+ def iterator
30
+ @node.neo_server.get_node_relationships(@node, @direction, @types)
31
+ end
32
+
33
+ def del
34
+ each { |rel| @node.neo_server.delete_relationship(rel) }
35
+ end
36
+
37
+ def size
38
+ [*self].size
39
+ end
40
+
41
+ def both
42
+ @direction = :both
43
+ self
44
+ end
45
+
46
+ def incoming
47
+ raise "Not allowed calling incoming when finding several relationships types" if @types
48
+ @direction = :incoming
49
+ self
50
+ end
51
+
52
+ def outgoing
53
+ raise "Not allowed calling outgoing when finding several relationships types" if @types
54
+ @direction = :outgoing
55
+ self
56
+ end
57
+
58
+ end
59
+ end
@@ -1,15 +1,21 @@
1
1
  module Neography
2
2
  class Rest
3
3
  include HTTParty
4
- attr_accessor :protocol, :server, :port, :log_file, :log_enabled, :logger
5
-
6
- def initialize(protocol='http://', server='localhost', port=7474, log_file='neography.log', log_enabled=false)
4
+ attr_accessor :protocol, :server, :port, :log_file, :log_enabled, :logger, :max_threads
5
+
6
+ def initialize(protocol=Neography::Config.protocol,
7
+ server=Neography::Config.server,
8
+ port=Neography::Config.port,
9
+ log_file=Neography::Config.log_file,
10
+ log_enabled=Neography::Config.log_enabled,
11
+ max_threads=Neography::Config.max_threads)
7
12
  @protocol = protocol
8
13
  @server = server
9
14
  @port = port
10
15
  @log_file = log_file
11
16
  @log_enabled = log_enabled
12
17
  @logger = Logger.new(@log_file) if @log_enabled
18
+ @max_threads = max_threads
13
19
  end
14
20
 
15
21
  def configure(protocol, server, port)
@@ -35,10 +41,67 @@ module Neography
35
41
  end
36
42
  end
37
43
 
44
+ def create_nodes(nodes)
45
+ nodes = Array.new(nodes) if nodes.kind_of? Fixnum
46
+ created_nodes = Array.new
47
+ nodes.each do |node|
48
+ created_nodes << create_node(node)
49
+ end
50
+ created_nodes
51
+ end
52
+
53
+ def create_nodes_threaded(nodes)
54
+ nodes = Array.new(nodes) if nodes.kind_of? Fixnum
55
+
56
+ node_queue = Queue.new
57
+ thread_pool = []
58
+ responses = Queue.new
59
+
60
+ nodes.each do |node|
61
+ node_queue.push node
62
+ end
63
+
64
+ [nodes.size, @max_threads].min.times do
65
+ thread_pool << Thread.new do
66
+ until node_queue.empty? do
67
+ node = node_queue.pop
68
+ if node.respond_to?(:each_pair)
69
+ responses.push( post("/node", { :body => node.to_json, :headers => {'Content-Type' => 'application/json'} } ) )
70
+ else
71
+ responses.push( post("/node") )
72
+ end
73
+ end
74
+ self.join
75
+ end
76
+ end
77
+
78
+ created_nodes = Array.new
79
+
80
+ while created_nodes.size < nodes.size
81
+ created_nodes << responses.pop
82
+ end
83
+ created_nodes
84
+ end
85
+
86
+ # This is not yet implemented in the REST API
87
+ #
88
+ # def get_all_node
89
+ # puts "get all nodes"
90
+ # get("/nodes/")
91
+ # end
92
+
38
93
  def get_node(id)
39
94
  get("/node/#{get_id(id)}")
40
95
  end
41
96
 
97
+ def get_nodes(*nodes)
98
+ gotten_nodes = Array.new
99
+ Array(nodes).flatten.each do |node|
100
+ gotten_nodes << get_node(node)
101
+ end
102
+ gotten_nodes
103
+ end
104
+
42
105
  def reset_node_properties(id, properties)
43
106
  options = { :body => properties.to_json, :headers => {'Content-Type' => 'application/json'} }
44
107
  put("/node/#{get_id(id)}/properties", options)
@@ -49,7 +112,7 @@ module Neography
49
112
  get("/node/#{get_id(id)}/properties")
50
113
  else
51
114
  node_properties = Hash.new
52
- properties.to_a.each do |property|
115
+ Array(properties).each do |property|
53
116
  value = get("/node/#{get_id(id)}/properties/#{property}")
54
117
  node_properties[property] = value unless value.nil?
55
118
  end
@@ -62,7 +125,7 @@ module Neography
62
125
  if properties.nil?
63
126
  delete("/node/#{get_id(id)}/properties")
64
127
  else
65
- properties.to_a.each do |property|
128
+ Array(properties).each do |property|
66
129
  delete("/node/#{get_id(id)}/properties/#{property}")
67
130
  end
68
131
  end
@@ -98,7 +161,7 @@ module Neography
98
161
  get("/relationship/#{get_id(id)}/properties")
99
162
  else
100
163
  relationship_properties = Hash.new
101
- properties.to_a.each do |property|
164
+ Array(properties).each do |property|
102
165
  value = get("/relationship/#{get_id(id)}/properties/#{property}")
103
166
  relationship_properties[property] = value unless value.nil?
104
167
  end
@@ -111,7 +174,7 @@ module Neography
111
174
  if properties.nil?
112
175
  delete("/relationship/#{get_id(id)}/properties")
113
176
  else
114
- properties.to_a.each do |property|
177
+ Array(properties).each do |property|
115
178
  delete("/relationship/#{get_id(id)}/properties/#{property}")
116
179
  end
117
180
  end
@@ -134,7 +197,7 @@ module Neography
134
197
  if types.nil?
135
198
  node_relationships = get("/node/#{get_id(id)}/relationships/#{dir}") || Array.new
136
199
  else
137
- node_relationships = get("/node/#{get_id(id)}/relationships/#{dir}/#{types.to_a.join('&')}") || Array.new
200
+ node_relationships = get("/node/#{get_id(id)}/relationships/#{dir}/#{Array(types).join('&')}") || Array.new
138
201
  end
139
202
  return nil if node_relationships.empty?
140
203
  node_relationships
@@ -235,6 +298,8 @@ module Neography
235
298
  id["self"].split('/').last
236
299
  when String
237
300
  id.split('/').last
301
+ when Neography::Node, Neography::Relationship
302
+ id.neo_id
238
303
  else
239
304
  id
240
305
  end
@@ -1,3 +1,3 @@
1
1
  module Neography
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
data/lib/neography.rb CHANGED
@@ -15,12 +15,28 @@ def find_and_require_user_defined_code
15
15
  end
16
16
  end
17
17
 
18
+ DIRECTIONS = ["incoming", "in", "outgoing", "out", "all", "both"]
19
+
18
20
 
19
21
  require 'httparty'
20
22
  require 'json'
21
23
  require 'logger'
24
+ require 'ostruct'
22
25
 
26
+ require 'neography/config'
23
27
  require 'neography/rest'
28
+ require 'neography/neography'
29
+
30
+ require 'neography/property_container'
31
+ require 'neography/property'
32
+ require 'neography/node_relationship'
33
+ require 'neography/relationship_traverser'
34
+ require 'neography/node_traverser'
35
+ require 'neography/equal'
36
+
37
+
38
+ require 'neography/node'
39
+ require 'neography/relationship'
24
40
 
25
41
  find_and_require_user_defined_code
26
42
 
@@ -0,0 +1,10 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ describe Neography do
4
+ describe "ref_node" do
5
+ it "can get the reference node" do
6
+ root_node = Neography.ref_node
7
+ root_node.should have_key("reference_node")
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,198 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ describe Neography::Node do
4
+
5
+ describe "create and new" do
6
+ it "can create an empty node" do
7
+ new_node = Neography::Node.create
8
+ new_node.should_not be_nil
9
+ end
10
+
11
+ it "can create a node with one property" do
12
+ new_node = Neography::Node.create("name" => "Max")
13
+ new_node.name.should == "Max"
14
+ end
15
+
16
+ it "can create a node with more than one property" do
17
+ new_node = Neography::Node.create("age" => 31, "name" => "Max")
18
+ new_node.name.should == "Max"
19
+ new_node.age.should == 31
20
+ end
21
+
22
+ it "can create a node with more than one property not on the default rest server" do
23
+ @neo = Neography::Rest.new
24
+ new_node = Neography::Node.create({"age" => 31, "name" => "Max"}, @neo)
25
+ new_node.name.should == "Max"
26
+ new_node.age.should == 31
27
+ end
28
+
29
+ it "can create a node with more than one property not on the default rest server the other way" do
30
+ @neo = Neography::Rest.new
31
+ new_node = Neography::Node.create(@neo, {"age" => 31, "name" => "Max"})
32
+ new_node.name.should == "Max"
33
+ new_node.age.should == 31
34
+ end
35
+ end
36
+
37
+
38
+ describe "load" do
39
+ it "can get a node that exists" do
40
+ new_node = Neography::Node.create
41
+ existing_node = Neography::Node.load(new_node)
42
+ existing_node.should_not be_nil
43
+ existing_node.neo_id.should_not be_nil
44
+ existing_node.neo_id.should == new_node.neo_id
45
+ end
46
+
47
+ it "returns nil if it tries to load a node that does not exist" do
48
+ new_node = Neography::Node.create
49
+ fake_node = new_node.neo_id.to_i + 1000
50
+ existing_node = Neography::Node.load(fake_node)
51
+ existing_node.should be_nil
52
+ end
53
+
54
+ it "can load a node that exists not on the default rest server" do
55
+ @neo = Neography::Rest.new
56
+ new_node = Neography::Node.create(@neo)
57
+ existing_node = Neography::Node.load(new_node, @neo)
58
+ existing_node.should_not be_nil
59
+ existing_node.neo_id.should_not be_nil
60
+ existing_node.neo_id.should == new_node.neo_id
61
+ end
62
+
63
+ it "can load a node that exists not on the default rest server the other way" do
64
+ @neo = Neography::Rest.new
65
+ new_node = Neography::Node.create(@neo)
66
+ existing_node = Neography::Node.load(@neo, new_node)
67
+ existing_node.should_not be_nil
68
+ existing_node.neo_id.should_not be_nil
69
+ existing_node.neo_id.should == new_node.neo_id
70
+ end
71
+ end
72
+
73
+ describe "del" do
74
+ it "can delete itself" do
75
+ new_node = Neography::Node.create
76
+ node_id = new_node.neo_id
77
+ new_node.del
78
+ deleted_node = Neography::Node.load(node_id)
79
+ deleted_node.should be_nil
80
+ end
81
+ end
82
+
83
+ describe "exists?" do
84
+ it "can tell if it exists" do
85
+ new_node = Neography::Node.create
86
+ new_node.exist?.should be_true
87
+ end
88
+
89
+ it "can tell if does not exists" do
90
+ new_node = Neography::Node.create
91
+ new_node.del
92
+ new_node.exist?.should be_false
93
+ end
94
+ end
95
+
96
+ describe "equality" do
97
+ it "can tell two nodes are the same with equal?" do
98
+ new_node = Neography::Node.create
99
+ another_node = Neography::Node.load(new_node)
100
+ new_node.equal?(another_node).should be_true
101
+ end
102
+
103
+ it "can tell two nodes are the same with eql?" do
104
+ new_node = Neography::Node.create
105
+ another_node = Neography::Node.load(new_node)
106
+ new_node.eql?(another_node).should be_true
107
+ end
108
+
109
+ it "can tell two nodes are the same with ==" do
110
+ new_node = Neography::Node.create
111
+ another_node = Neography::Node.load(new_node)
112
+ (new_node == another_node).should be_true
113
+ end
114
+ end
115
+
116
+ describe "set properties" do
117
+ it "can change a node's properties that already exist using []=" do
118
+ new_node = Neography::Node.create("weight" => 150, "eyes" => "green")
119
+
120
+ new_node[:weight] = 200
121
+ new_node[:eyes] = "brown"
122
+
123
+ existing_node = Neography::Node.load(new_node)
124
+ existing_node.weight.should == 200
125
+ existing_node.eyes.should == "brown"
126
+ end
127
+
128
+ it "can change a node's properties that already exist" do
129
+ new_node = Neography::Node.create("weight" => 150, "eyes" => "green")
130
+
131
+ new_node.weight = 200
132
+ new_node.eyes = "brown"
133
+
134
+ existing_node = Neography::Node.load(new_node)
135
+ existing_node.weight.should == 200
136
+ existing_node.eyes.should == "brown"
137
+ end
138
+
139
+ it "can change a node's properties that does not already exist" do
140
+ new_node = Neography::Node.create("weight" => 150, "eyes" => "green")
141
+
142
+ new_node.weight = 200
143
+ new_node.eyes = "brown"
144
+ new_node[:hair] = "black"
145
+
146
+ existing_node = Neography::Node.load(new_node)
147
+ existing_node.weight.should == 200
148
+ existing_node.eyes.should == "brown"
149
+ existing_node.hair.should == "black"
150
+ end
151
+ end
152
+
153
+ describe "get node properties" do
154
+ it "can get node properties using []" do
155
+ new_node = Neography::Node.create("weight" => 150, "eyes" => "green")
156
+ new_node[:weight].should == 150
157
+ new_node[:eyes].should == "green"
158
+ end
159
+
160
+ it "can get node properties" do
161
+ new_node = Neography::Node.create("weight" => 150, "eyes" => "green")
162
+ new_node.weight.should == 150
163
+ new_node.eyes.should == "green"
164
+ end
165
+ end
166
+
167
+ describe "delete node properties" do
168
+ it "can delete node properties using []" do
169
+ new_node = Neography::Node.create("weight" => 150, "eyes" => "green")
170
+
171
+ new_node[:weight] = nil
172
+ new_node[:eyes] = nil
173
+
174
+ new_node[:weight].should be_nil
175
+ new_node[:eyes].should be_nil
176
+
177
+ existing_node = Neography::Node.load(new_node)
178
+ existing_node.weight.should be_nil
179
+ existing_node.eyes.should be_nil
180
+ end
181
+
182
+ it "can delete node properties" do
183
+ new_node = Neography::Node.create("weight" => 150, "eyes" => "green")
184
+
185
+ new_node.weight = nil
186
+ new_node.eyes = nil
187
+
188
+ new_node.weight.should be_nil
189
+ new_node.eyes.should be_nil
190
+
191
+ existing_node = Neography::Node.load(new_node)
192
+ existing_node.weight.should be_nil
193
+ existing_node.eyes.should be_nil
194
+ end
195
+ end
196
+
197
+
198
+ end
@@ -0,0 +1,71 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ describe Neography::Relationship do
4
+ describe "create relationship" do
5
+ it "#new(:family, p1, p2) creates a new relationship between to nodes of given type" do
6
+ p1 = Neography::Node.create
7
+ p2 = Neography::Node.create
8
+
9
+ new_rel = Neography::Relationship.create(:family, p1, p2)
10
+ puts new_rel.inspect
11
+ new_rel.start_node.should == p1
12
+ new_rel.end_node.should == p2
13
+
14
+
15
+ # p1.outgoing(:family).should include(p2)
16
+ # p2.incoming(:family).should include(p1)
17
+ end
18
+
19
+ it "#new(:family, p1, p2, :since => '1998', :colour => 'blue') creates relationship and sets its properties" do
20
+ p1 = Neography::Node.create
21
+ p2 = Neography::Node.create
22
+
23
+ rel = Neography::Relationship.create(:family, p1, p2, :since => 1998, :colour => 'blue')
24
+ rel[:since].should == 1998
25
+ rel[:colour].should == 'blue'
26
+ rel.since.should == 1998
27
+ rel.colourshould == 'blue'
28
+ end
29
+
30
+ it "#outgoing(:friends).create(other) creates a new relationship between self and other node" do
31
+ p1 = Neography::Node.create
32
+ p2 = Neography::Node.create
33
+
34
+ rel = p1.outgoing(:foo).create(p2)
35
+ p1.outgoing(:foo).first.should == p2
36
+ rel.should be_kind_of(Neography::Relationship)
37
+ end
38
+ end
39
+
40
+ describe "rel?" do
41
+ it "#rel? returns true if there are any relationships" do
42
+ n1 = Neography::Node.create
43
+ n2 = Neography::Node.create
44
+ new_rel = Neography::Relationship.create(:foo, n1, n2)
45
+ n1.rel?.should be_true
46
+ n1.rel?(:bar).should be_false
47
+ n1.rel?(:foo).should be_true
48
+ n1.rel?(:incoming, :foo).should be_false
49
+ n1.rel?(:outgoing, :foo).should be_true
50
+ n1.rel?(:foo, :incoming).should be_false
51
+ n1.rel?(:foo, :outgoing).should be_true
52
+
53
+ n1.rel?(:incoming).should be_false
54
+ n1.rel?(:outgoing).should be_true
55
+ n1.rel?(:both).should be_true
56
+ n1.rel?(:all).should be_true
57
+ n1.rel?.should be_true
58
+ end
59
+ end
60
+
61
+
62
+ describe "delete relationship" do
63
+ it "can delete an existing relationship" do
64
+ p1 = Neography::Node.create
65
+ p2 = Neography::Node.create
66
+ new_rel = Neography::Relationship.create(:family, p1, p2)
67
+ new_rel.del
68
+ Neography::Relationship.load(new_rel).should be_nil
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,106 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ describe Neography::Rest do
4
+ before(:each) do
5
+ @neo = Neography::Rest.new
6
+ end
7
+
8
+ describe "can create many nodes threaded" do
9
+ it "can create empty nodes threaded" do
10
+ new_nodes = @neo.create_nodes_threaded(2)
11
+ new_nodes.should_not be_nil
12
+ new_nodes.size.should == 2
13
+ end
14
+
15
+ it "is faster than non-threaded?" do
16
+ Benchmark.bm do |x|
17
+ x.report("create 500 nodes ") { @not_threaded = @neo.create_nodes(500) }
18
+ x.report("create 500 nodes threaded") { @threaded = @neo.create_nodes_threaded(500) }
19
+ x.report("create 1000 nodes threaded") { @threaded2c = @neo.create_nodes_threaded(1000) }
20
+ end
21
+
22
+ @not_threaded[99].should_not be_nil
23
+ @threaded[99].should_not be_nil
24
+ @threaded2c[199].should_not be_nil
25
+ end
26
+
27
+ end
28
+
29
+ describe "can create many nodes" do
30
+ it "can create empty nodes" do
31
+ new_nodes = @neo.create_nodes(2)
32
+ new_nodes.should_not be_nil
33
+ new_nodes.size.should == 2
34
+ end
35
+
36
+ it "can create nodes with one property" do
37
+ new_nodes = @neo.create_nodes([{"name" => "Max"}, {"name" => "Alex"}])
38
+ new_nodes[0]["data"]["name"].should == "Max"
39
+ new_nodes[1]["data"]["name"].should == "Alex"
40
+ end
41
+
42
+ it "can create nodes with one property that are different" do
43
+ new_nodes = @neo.create_nodes([{"name" => "Max"}, {"age" => 24}])
44
+ new_nodes[0]["data"]["name"].should == "Max"
45
+ new_nodes[1]["data"]["age"].should == 24
46
+ end
47
+
48
+ it "can create nodes with more than one property" do
49
+ new_nodes = @neo.create_nodes([{"age" => 31, "name" => "Max"}, {"age" => 24, "name" => "Alex"}])
50
+ new_nodes[0]["data"]["name"].should == "Max"
51
+ new_nodes[0]["data"]["age"].should == 31
52
+ new_nodes[1]["data"]["name"].should == "Alex"
53
+ new_nodes[1]["data"]["age"].should == 24
54
+ end
55
+
56
+ it "can create nodes with more than one property that are different" do
57
+ new_nodes = @neo.create_nodes([{"age" => 31, "name" => "Max"}, {"height" => "5-11", "weight" => 215}])
58
+ new_nodes[0]["data"]["name"].should == "Max"
59
+ new_nodes[0]["data"]["age"].should == 31
60
+ new_nodes[1]["data"]["height"].should == "5-11"
61
+ new_nodes[1]["data"]["weight"].should == 215
62
+ end
63
+
64
+ it "is not super slow?" do
65
+ Benchmark.bm do |x|
66
+ x.report( "create 1 node" ) { @neo.create_nodes( 1) }
67
+ x.report( "create 10 nodes") { @neo.create_nodes( 10) }
68
+ x.report("create 100 nodes") { @neo.create_nodes(100) }
69
+ end
70
+ end
71
+ end
72
+
73
+ describe "can get many nodes" do
74
+ it "can get 2 nodes passed in as an array" do
75
+ new_nodes = @neo.create_nodes(2)
76
+ existing_nodes = @neo.get_nodes(new_nodes)
77
+ existing_nodes.should_not be_nil
78
+ existing_nodes.size.should == 2
79
+ end
80
+
81
+ it "can get 2 nodes passed in by commas" do
82
+ new_nodes = @neo.create_nodes(2)
83
+ new_node1 = new_nodes[0]["self"].split('/').last
84
+ new_node2 = new_nodes[1]["self"].split('/').last
85
+ existing_nodes = @neo.get_nodes(new_node1, new_node2)
86
+ existing_nodes.should_not be_nil
87
+ existing_nodes.size.should == 2
88
+ existing_nodes[0]["self"] == new_node1["self"]
89
+ existing_nodes[1]["self"] == new_node2["self"]
90
+ end
91
+
92
+ it "is not super slow?" do
93
+ one_node = @neo.create_nodes( 1)
94
+ ten_nodes = @neo.create_nodes( 10)
95
+ one_hundred_nodes = @neo.create_nodes(100)
96
+
97
+ Benchmark.bm do |x|
98
+ x.report( "get 1 node ") { @neo.get_nodes(one_node) }
99
+ x.report( "get 10 nodes") { @neo.get_nodes(ten_nodes) }
100
+ x.report("get 100 nodes") { @neo.get_nodes(one_hundred_nodes) }
101
+ end
102
+ end
103
+
104
+ end
105
+
106
+ end
@@ -0,0 +1,23 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ describe Neography::Rest do
4
+ before(:each) do
5
+ @neo = Neography::Rest.new
6
+ end
7
+
8
+
9
+ describe "get_nodes" do
10
+ it "can get nodes that exists" do
11
+ existing_nodes = @neo.get_nodes
12
+ existing_nodes.should_not be_nil
13
+ puts existing_nodes.inspect
14
+ end
15
+
16
+ it "can get all nodes that exists the ugly way" do
17
+ new_node = @neo.create_node
18
+ last_node_id = new_node["self"].split('/').last.to_i
19
+ existing_nodes = @neo.get_nodes((1..last_node_id).to_a)
20
+ existing_nodes.should_not be_nil
21
+ end
22
+ end
23
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'neography'
2
2
  require 'fakeweb'
3
+ require 'benchmark'
3
4
 
4
5
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
5
6
 
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 4
9
- version: 0.0.4
8
+ - 5
9
+ version: 0.0.5
10
10
  platform: ruby
11
11
  authors:
12
12
  - Max De Marzi
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-11-21 00:00:00 -08:00
17
+ date: 2010-12-08 00:00:00 -08:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -112,9 +112,24 @@ files:
112
112
  - examples/linkedin.rb
113
113
  - examples/traversal_example1.rb
114
114
  - lib/neography.rb
115
+ - lib/neography/config.rb
116
+ - lib/neography/equal.rb
117
+ - lib/neography/neography.rb
118
+ - lib/neography/node.rb
119
+ - lib/neography/node_relationship.rb
120
+ - lib/neography/node_traverser.rb
121
+ - lib/neography/property.rb
122
+ - lib/neography/property_container.rb
123
+ - lib/neography/relationship.rb
124
+ - lib/neography/relationship_traverser.rb
115
125
  - lib/neography/rest.rb
116
126
  - lib/neography/version.rb
117
127
  - neography.gemspec
128
+ - spec/integration/neography_spec.rb
129
+ - spec/integration/node_spec.rb
130
+ - spec/integration/relationship_spec.rb
131
+ - spec/integration/rest_bulk_spec.rb
132
+ - spec/integration/rest_experimental_spec.rb
118
133
  - spec/integration/rest_index_spec.rb
119
134
  - spec/integration/rest_node_spec.rb
120
135
  - spec/integration/rest_path_spec.rb