neo4jr-social 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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