neo4jr-social 0.1.0

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.
@@ -0,0 +1,3 @@
1
+ module Neo4jr::Social
2
+ VERSION = File.read(File.expand_path(File.dirname(__FILE__) + "/../../VERSION")) unless defined?(Neo4jr::Social::VERSION)
3
+ end
@@ -0,0 +1,97 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{neo4jr-social}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Matthew Deiters"]
12
+ s.date = %q{2009-12-23}
13
+ s.default_executable = %q{start-neo4jr-social}
14
+ s.description = %q{A self-containted lightweight REST interface to Neo4j using JRuby }
15
+ s.email = %q{matthew_deiters@mckinsey.com}
16
+ s.executables = ["start-neo4jr-social"]
17
+ s.extra_rdoc_files = [
18
+ "LICENSE",
19
+ "README.rdoc",
20
+ "TODO"
21
+ ]
22
+ s.files = [
23
+ ".document",
24
+ ".gitignore",
25
+ "LICENSE",
26
+ "README.rdoc",
27
+ "Rakefile",
28
+ "TODO",
29
+ "VERSION",
30
+ "bin/start-neo4jr-social",
31
+ "config.ru",
32
+ "examples/facebook.rb",
33
+ "examples/linkedin.rb",
34
+ "jetty-runtime/etc/jetty.xml",
35
+ "jetty-runtime/etc/webdefault.xml",
36
+ "jetty-runtime/lib/jetty-6.1.3.jar",
37
+ "jetty-runtime/lib/jetty-util-6.1.3.jar",
38
+ "jetty-runtime/lib/jsp-2.1/ant-1.6.5.jar",
39
+ "jetty-runtime/lib/jsp-2.1/core-3.1.1.jar",
40
+ "jetty-runtime/lib/jsp-2.1/jsp-2.1.jar",
41
+ "jetty-runtime/lib/jsp-2.1/jsp-api-2.1.jar",
42
+ "jetty-runtime/lib/servlet-api-2.5-6.1.3.jar",
43
+ "jetty-runtime/start.jar",
44
+ "jetty-runtime/webapps/neo4jr-social.war",
45
+ "lib/neo4jr-social.rb",
46
+ "lib/neo4jr-social/service.rb",
47
+ "lib/neo4jr-social/version.rb",
48
+ "neo4jr-social.gemspec",
49
+ "spec/service_spec.rb",
50
+ "spec/spec.opts",
51
+ "spec/spec_helper.rb",
52
+ "tmp/war/WEB-INF/lib/jruby-core-1.4.0.jar",
53
+ "tmp/war/WEB-INF/lib/jruby-rack-0.9.5.jar",
54
+ "tmp/war/WEB-INF/lib/jruby-stdlib-1.4.0.jar",
55
+ "tmp/war/WEB-INF/lib/neo4jr-social.rb",
56
+ "tmp/war/WEB-INF/lib/neo4jr-social/service.rb",
57
+ "tmp/war/WEB-INF/lib/neo4jr-social/version.rb",
58
+ "tmp/war/WEB-INF/web.xml"
59
+ ]
60
+ s.homepage = %q{http://github.com/mdeiters/neo4jr-social}
61
+ s.rdoc_options = ["--charset=UTF-8"]
62
+ s.require_paths = ["lib"]
63
+ s.rubygems_version = %q{1.3.5}
64
+ s.summary = %q{A self-containted and lightweight REST interface to Neo4j using JRuby.}
65
+ s.test_files = [
66
+ "spec/service_spec.rb",
67
+ "spec/spec_helper.rb",
68
+ "examples/facebook.rb",
69
+ "examples/linkedin.rb"
70
+ ]
71
+
72
+ if s.respond_to? :specification_version then
73
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
74
+ s.specification_version = 3
75
+
76
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
77
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
78
+ s.add_development_dependency(%q<rest-client>, [">= 0"])
79
+ s.add_runtime_dependency(%q<neo4jr-simple>, [">= 0"])
80
+ s.add_runtime_dependency(%q<sinatra>, [">= 0"])
81
+ s.add_runtime_dependency(%q<json_pure>, [">= 0"])
82
+ else
83
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
84
+ s.add_dependency(%q<rest-client>, [">= 0"])
85
+ s.add_dependency(%q<neo4jr-simple>, [">= 0"])
86
+ s.add_dependency(%q<sinatra>, [">= 0"])
87
+ s.add_dependency(%q<json_pure>, [">= 0"])
88
+ end
89
+ else
90
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
91
+ s.add_dependency(%q<rest-client>, [">= 0"])
92
+ s.add_dependency(%q<neo4jr-simple>, [">= 0"])
93
+ s.add_dependency(%q<sinatra>, [">= 0"])
94
+ s.add_dependency(%q<json_pure>, [">= 0"])
95
+ end
96
+ end
97
+
@@ -0,0 +1,112 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Neo4jr::Service do
4
+
5
+ it "should be able to create a node" do
6
+ post '/nodes', 'some_property=a_value&type=person'
7
+ node = response_to_ruby
8
+ node.should have_key('node_id')
9
+ node['type'].should == 'person'
10
+ node['some_property'].should == 'a_value'
11
+ end
12
+
13
+ it 'should be able to delete a node' do
14
+ post '/nodes', 'type=person'
15
+ node = response_to_ruby
16
+ delete "/nodes/#{node['node_id']}"
17
+ last_response.status.should == 200
18
+ last_response.body.should be_empty
19
+ end
20
+
21
+ it 'should be able to update a node' do
22
+ post '/nodes', 'some_property=a_value&type=person'
23
+ node = response_to_ruby
24
+ put "/nodes/#{node['node_id']}", 'some_property=changed_value'
25
+ node = response_to_ruby
26
+ node['some_property'].should == 'changed_value'
27
+ end
28
+
29
+ it 'should be able to add relationships to nodes' do
30
+ post '/nodes', {:name => 'Philip Seymour Hoffman'}
31
+ actor = response_to_ruby
32
+
33
+ post '/nodes', {:title => 'The Invention of Lying'}
34
+ movie = response_to_ruby
35
+
36
+ post "/nodes/#{actor['node_id']}/relationships", { :to => movie['node_id'], :type => 'acted_in' }
37
+ last_response.status.should == 200
38
+ relationships = response_to_ruby
39
+ relationships.size.should == 1
40
+ end
41
+
42
+ it 'should return relationships with the to node and type and any other properties added' do
43
+ post '/nodes', {:name => 'Philip Seymour Hoffman'}
44
+ actor = response_to_ruby
45
+
46
+ post '/nodes', {:title => 'The Invention of Lying'}
47
+ movie = response_to_ruby
48
+
49
+ post "/nodes/#{actor['node_id']}/relationships", { :to => movie['node_id'], :type => 'acted_in', :year => 2009 }
50
+ relationship = response_to_ruby.first
51
+ relationship['year'].should == '2009'
52
+ relationship['type'].should == 'acted_in'
53
+ relationship['to'].should == movie['node_id']
54
+ end
55
+
56
+ describe 'degrees of seperation using shortest path' do
57
+ let(:actor1) { post('/nodes', {:name => 'Philip Seymour Hoffman'}) && response_to_ruby }
58
+ let(:actor2) { post('/nodes', {:name => 'Tina Fey'}) && response_to_ruby}
59
+ let(:movie) { post('/nodes', {:title => 'The Invention of Lying'}) && response_to_ruby}
60
+
61
+ it 'determines degrees of seperation between nodes like LinkedIn' do
62
+ post "/nodes/#{actor1['node_id']}/relationships", { :to => movie['node_id'], :type => 'acted_in', :year => 2009 }
63
+ post "/nodes/#{actor2['node_id']}/relationships", { :to => movie['node_id'], :type => 'acted_in', :year => 2009 }
64
+
65
+ get "/nodes/#{actor1['node_id']}/path", { :to => actor2['node_id'], :type => 'acted_in'}
66
+ last_response.status.should == 200
67
+ paths = response_to_ruby
68
+ first_path = paths.first
69
+ first_path[0]['name'].should == 'Philip Seymour Hoffman'
70
+ first_path[2]['title'].should == 'The Invention of Lying'
71
+ first_path[4]['name'].should == 'Tina Fey'
72
+ end
73
+
74
+ end
75
+
76
+ describe 'suggestions' do
77
+ let(:hoffman) { post('/nodes', {:name => 'Philip Seymour Hoffman'}) && response_to_ruby }
78
+ let(:fey) { post( '/nodes', {:name => 'Tina Fey'}) && response_to_ruby}
79
+ let(:hanks) { post( '/nodes', {:name => 'Tom Hanks'}) && response_to_ruby}
80
+ let(:murphy) { post( '/nodes', {:name => 'Brittney Murphy'}) && response_to_ruby}
81
+ let(:bale) { post( '/nodes', {:name => 'Christian Bale'}) && response_to_ruby}
82
+
83
+ before :each do
84
+ create_mutual_friends = Proc.new do |node1, node2|
85
+ post "/nodes/#{node1['node_id']}/relationships", { :to => node2['node_id'], :type => 'friends' }
86
+ post "/nodes/#{node2['node_id']}/relationships", { :to => node1['node_id'], :type => 'friends' }
87
+ end
88
+
89
+ create_mutual_friends.call(hoffman, fey)
90
+ create_mutual_friends.call(hoffman, murphy)
91
+ create_mutual_friends.call(murphy, fey)
92
+ create_mutual_friends.call(murphy, hanks)
93
+ create_mutual_friends.call(hanks, bale)
94
+ end
95
+
96
+ it "gets my friend's friends that I'm not friends with as suggestions" do
97
+ get "/nodes/#{hoffman['node_id']}/recommendations?type=friends"
98
+ last_response.status.should == 200
99
+ suggestions = response_to_ruby
100
+ suggestions.size.should == 1
101
+ suggestions.first['name'].should == 'Tom Hanks'
102
+ end
103
+
104
+ it "gets my friend's friend's friends that I'm not friends with as suggestions" do
105
+ get "/nodes/#{hoffman['node_id']}/recommendations?type=friends&level=2"
106
+ last_response.status.should == 200
107
+ suggestions = response_to_ruby
108
+ suggestions.size.should == 1
109
+ suggestions.first['name'].should == 'Christian Bale'
110
+ end
111
+ end
112
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,22 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+
4
+ # $LOAD_PATH.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '..', '..', 'neo4jr-simple', 'lib'))
5
+ # require 'neo4jr-simple'
6
+
7
+ require 'neo4jr-social'
8
+ require 'spec'
9
+ require 'spec/autorun'
10
+ require 'rack/test'
11
+
12
+ Spec::Runner.configure do |config|
13
+ include Rack::Test::Methods
14
+
15
+ def app
16
+ Neo4jr::Service
17
+ end
18
+
19
+ def response_to_ruby
20
+ JSON.parse(last_response.body)
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)))
2
+
3
+ include Java
4
+
5
+ require 'rubygems'
6
+ gem 'sinatra'
7
+ gem 'json_pure'
8
+ gem 'neo4jr-simple'
9
+
10
+ require 'sinatra'
11
+ require 'json'
12
+ require 'neo4jr-simple'
13
+ require 'neo4jr-social/service'
14
+
@@ -0,0 +1,97 @@
1
+ module Neo4jr
2
+ class Service < Sinatra::Base
3
+
4
+ get '/info' do
5
+ Neo4jr::DB.stats.to_json
6
+ end
7
+
8
+ get '/nodes' do
9
+ nodes = Neo4jr::DB.execute do |neo|
10
+ nodes = neo.all_nodes.map{|m| m.to_hash }
11
+ end
12
+ nodes.to_json
13
+ end
14
+
15
+ post '/nodes' do
16
+ node = Neo4jr::DB.execute do |neo|
17
+ node = neo.create_node(params)
18
+ end
19
+ node.to_hash.to_json
20
+ end
21
+
22
+ get '/nodes/:node_id' do
23
+ Neo4jr::DB.getNodeById(params.delete('node_id')).to_json
24
+ end
25
+
26
+ put '/nodes/:node_id' do
27
+ node = Neo4jr::DB.execute do |neo|
28
+ node = neo.getNodeById(params.delete('node_id'))
29
+ node.update_properties(params)
30
+ end
31
+ node.to_hash.to_json
32
+ end
33
+
34
+ delete '/nodes/:node_id' do
35
+ Neo4jr::DB.execute do |neo|
36
+ node = neo.getNodeById(params['node_id'])
37
+ node.delete
38
+ end
39
+ end
40
+
41
+ get '/nodes/:node_id/relationships' do
42
+ relationships = Neo4jr::DB.execute do |neo|
43
+ node = neo.getNodeById(params.delete('node_id'))
44
+ if relationship_type = params.delete('type')
45
+ relationship_type = RelationshipType.instance(relationship_type)
46
+ node.getRelationships(relationship_type.to_a).hashify_objects
47
+ else
48
+ node.getRelationships.hashify_objects
49
+ end
50
+ end
51
+ relationships.to_json
52
+ end
53
+
54
+ post '/nodes/:node_id/relationships' do
55
+ relationships = Neo4jr::DB.execute do |neo|
56
+ node = neo.getNodeById(params.delete('node_id'))
57
+ to_node = neo.getNodeById(params.delete('to'))
58
+ relationship_type = RelationshipType.instance(params.delete('type'))
59
+ relationship = node.create_relationship_to to_node, relationship_type
60
+ relationship.update_properties(params)
61
+ node.getRelationships(relationship_type.to_a).hashify_objects
62
+ end
63
+ relationships.to_json
64
+ end
65
+
66
+ #optional direction & depth
67
+ get '/nodes/:node_id/path' do
68
+ paths = Neo4jr::DB.execute do |neo|
69
+ relationship = Neo4jr::RelationshipType.instance(params.delete('type'))
70
+ start_node = neo.getNodeById(params.delete('node_id'))
71
+ end_node = neo.getNodeById(params.delete('to'))
72
+ depth = params.delete('depth') || 2
73
+ direction = Neo4jr::Direction.from_string(params.delete('direction') || 'both')
74
+ shortest_path = AllSimplePaths.new(start_node, end_node, depth.to_i, direction, relationship.to_a)
75
+ paths = shortest_path.getPaths
76
+ paths.map{|p| p.map{|n| n.to_hash }}
77
+ end
78
+ paths.to_json
79
+ end
80
+
81
+ #optional
82
+ get '/nodes/:node_id/recommendations' do
83
+ suggestions = Neo4jr::DB.execute do |neo|
84
+ relationship = Neo4jr::RelationshipType.incoming(params.delete('type'))
85
+ start_node = neo.getNodeById(params.delete('node_id'))
86
+ level = (params.delete('level') || 1).to_i
87
+ order = Order::BREADTH_FIRST
88
+ return_when = Return.when do |current_position|
89
+ current_position.depth > level
90
+ end
91
+ traverser = start_node.traverse(order, Stop.at(level + 1), return_when, relationship)
92
+ traverser.map{|node| node.to_hash }
93
+ end
94
+ suggestions.to_json
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,3 @@
1
+ module Neo4jr::Social
2
+ VERSION = File.read(File.expand_path(File.dirname(__FILE__) + "/../../VERSION")) unless defined?(Neo4jr::Social::VERSION)
3
+ end
@@ -0,0 +1,38 @@
1
+ <!DOCTYPE web-app PUBLIC
2
+ "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
3
+ "http://java.sun.com/dtd/web-app_2_3.dtd">
4
+ <web-app>
5
+
6
+ <context-param>
7
+ <param-name>rails.env</param-name>
8
+ <param-value>production</param-value>
9
+ </context-param>
10
+
11
+ <context-param>
12
+ <param-name>public.root</param-name>
13
+ <param-value>/</param-value>
14
+ </context-param>
15
+
16
+ <context-param>
17
+ <param-name>rackup</param-name>
18
+ <param-value>require 'lib/neo4jr-social'
19
+
20
+ run Neo4jr::Service</param-value>
21
+ </context-param>
22
+
23
+
24
+ <filter>
25
+ <filter-name>RackFilter</filter-name>
26
+ <filter-class>org.jruby.rack.RackFilter</filter-class>
27
+ </filter>
28
+ <filter-mapping>
29
+ <filter-name>RackFilter</filter-name>
30
+ <url-pattern>/*</url-pattern>
31
+ </filter-mapping>
32
+
33
+ <listener>
34
+ <listener-class>org.jruby.rack.RackServletContextListener</listener-class>
35
+ </listener>
36
+
37
+
38
+ </web-app>
metadata ADDED
@@ -0,0 +1,144 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: neo4jr-social
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Matthew Deiters
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-12-23 00:00:00 -08:00
13
+ default_executable: start-neo4jr-social
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.2.9
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: rest-client
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: neo4jr-simple
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: sinatra
47
+ type: :runtime
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ - !ruby/object:Gem::Dependency
56
+ name: json_pure
57
+ type: :runtime
58
+ version_requirement:
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ description: "A self-containted lightweight REST interface to Neo4j using JRuby "
66
+ email: matthew_deiters@mckinsey.com
67
+ executables:
68
+ - start-neo4jr-social
69
+ extensions: []
70
+
71
+ extra_rdoc_files:
72
+ - LICENSE
73
+ - README.rdoc
74
+ - TODO
75
+ files:
76
+ - .document
77
+ - .gitignore
78
+ - LICENSE
79
+ - README.rdoc
80
+ - Rakefile
81
+ - TODO
82
+ - VERSION
83
+ - bin/start-neo4jr-social
84
+ - config.ru
85
+ - examples/facebook.rb
86
+ - examples/linkedin.rb
87
+ - jetty-runtime/etc/jetty.xml
88
+ - jetty-runtime/etc/webdefault.xml
89
+ - jetty-runtime/lib/jetty-6.1.3.jar
90
+ - jetty-runtime/lib/jetty-util-6.1.3.jar
91
+ - jetty-runtime/lib/jsp-2.1/ant-1.6.5.jar
92
+ - jetty-runtime/lib/jsp-2.1/core-3.1.1.jar
93
+ - jetty-runtime/lib/jsp-2.1/jsp-2.1.jar
94
+ - jetty-runtime/lib/jsp-2.1/jsp-api-2.1.jar
95
+ - jetty-runtime/lib/servlet-api-2.5-6.1.3.jar
96
+ - jetty-runtime/start.jar
97
+ - jetty-runtime/webapps/neo4jr-social.war
98
+ - lib/neo4jr-social.rb
99
+ - lib/neo4jr-social/service.rb
100
+ - lib/neo4jr-social/version.rb
101
+ - neo4jr-social.gemspec
102
+ - spec/service_spec.rb
103
+ - spec/spec.opts
104
+ - spec/spec_helper.rb
105
+ - tmp/war/WEB-INF/lib/jruby-core-1.4.0.jar
106
+ - tmp/war/WEB-INF/lib/jruby-rack-0.9.5.jar
107
+ - tmp/war/WEB-INF/lib/jruby-stdlib-1.4.0.jar
108
+ - tmp/war/WEB-INF/lib/neo4jr-social.rb
109
+ - tmp/war/WEB-INF/lib/neo4jr-social/service.rb
110
+ - tmp/war/WEB-INF/lib/neo4jr-social/version.rb
111
+ - tmp/war/WEB-INF/web.xml
112
+ has_rdoc: true
113
+ homepage: http://github.com/mdeiters/neo4jr-social
114
+ licenses: []
115
+
116
+ post_install_message:
117
+ rdoc_options:
118
+ - --charset=UTF-8
119
+ require_paths:
120
+ - lib
121
+ required_ruby_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: "0"
126
+ version:
127
+ required_rubygems_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: "0"
132
+ version:
133
+ requirements: []
134
+
135
+ rubyforge_project:
136
+ rubygems_version: 1.3.5
137
+ signing_key:
138
+ specification_version: 3
139
+ summary: A self-containted and lightweight REST interface to Neo4j using JRuby.
140
+ test_files:
141
+ - spec/service_spec.rb
142
+ - spec/spec_helper.rb
143
+ - examples/facebook.rb
144
+ - examples/linkedin.rb