neo4r 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 38c41f26322670c74f7c715c4a6ebb420f7d2280
4
+ data.tar.gz: a5d6264214419449d7b4162df24701add7b6b915
5
+ SHA512:
6
+ metadata.gz: 457d03a1975c88bf9a44ab54c599ff41e4f63f64ddbba892516dccd981537b740f18f4c5ab55fb5a683f14e198bbf9099c9e80053f779fe512c922cc6a2d143f
7
+ data.tar.gz: f4da9b851ca5d6e2b8e4ffbcad5d9dbe91dbdb8d62cc2b495b535895cf4af7b59639b638a524f1754f7282ca794cd590f45ea35c043b8e8cf9b95524702c6103
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in neo4r.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Hiroyuki Sato
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,130 @@
1
+ # Neo4r
2
+
3
+ Neo4r is an Active Model compliant Ruby wrapper for [the Neo4j graph database](http://neo4j.com/). It uses [the Neography](https://github.com/maxdemarzi/neography) gems.
4
+
5
+
6
+ ## Requirement
7
+
8
+ - ruby ~> 2.1
9
+ - neography ~> 1.6
10
+
11
+ ## Neo4j version support
12
+
13
+ - 2.0.x
14
+ - 2.1.x
15
+
16
+ ## Installation
17
+
18
+ Add this line to your application's Gemfile:
19
+
20
+ ```ruby
21
+ gem 'neo4r'
22
+ ```
23
+
24
+ And then execute:
25
+
26
+ $ bundle
27
+
28
+ Or install it yourself as:
29
+
30
+ $ gem install neo4r
31
+
32
+ ## Usage
33
+
34
+ ### Configuration
35
+
36
+ Neo4r uses Neography to handle Neo4j REST API. So the configuration is same with Neography.
37
+ Please see [the Neography document](https://github.com/maxdemarzi/neography/tree/v1.6.0#configuration-and-initialization).
38
+
39
+ ### Modeling
40
+
41
+ A sample Node model.
42
+
43
+ ```ruby
44
+ class User < Neo4r::Node
45
+ end
46
+ ```
47
+
48
+ Create a new node.
49
+
50
+ ```ruby
51
+ user = User.new
52
+ user.name = "Hiroyuki Sato"
53
+ user.mail = "hiroyuki@example.com"
54
+ user.age = 35
55
+ user.save # => true
56
+ ```
57
+
58
+ Search nodes.
59
+ **The syntax of an exact match is only implemented.**
60
+
61
+ ```ruby
62
+ users = User.where(name: "Hiroyuki Sato")
63
+ puts users.first.name # => "Hiroyuki Sato"
64
+ ```
65
+
66
+ Update nodes.
67
+
68
+ ```ruby
69
+ user = User.where(name: "Hiroyuki Sato").first
70
+ user.age = 36
71
+ user.save # => true
72
+ ```
73
+
74
+ Delete nodes.
75
+
76
+ ```ruby
77
+ user = User.where(name: "Hiroyuki Sato").first
78
+ user.destroy => true
79
+ ```
80
+
81
+ Add connection.
82
+
83
+ ```ruby
84
+ ozawa = User.new
85
+ ozawa.name = "Kunio Ozawa"
86
+ ozawa.save
87
+
88
+ sato = User.new
89
+ sato.name = "Hiroyuki Sato"
90
+ sato.save
91
+
92
+ nakamura = User.new
93
+ nakamura.name = "Hiroyuki Nakamura"
94
+ nakamura.save
95
+
96
+ sugahara = User.new
97
+ sugahara.name = "Junichi Sugahara"
98
+ sugahara.save
99
+
100
+ nakamura.incoming(:boss) << ozawa
101
+ nakamura.incoming(:boss) << sato
102
+ sugahara.incoming(:boss) << nakamura
103
+ ```
104
+
105
+ Traverse connection.
106
+
107
+ ```ruby
108
+ sugahara.incoming(:boss).each { |user| puts user.name }
109
+ # output
110
+ # => "Hiroyuki Nakamura"
111
+ sugahara.incoming(:boss).depth(:all).each { |user| puts user.name }
112
+ # output
113
+ # => "Hiroyuki Nakamura"
114
+ # => "Hiroyuki Sato"
115
+ # => "Kunio Ozawa"
116
+ ```
117
+
118
+ Delete connection.
119
+
120
+ ```ruby
121
+ nakamura.rels(:boss).to_other(sato).destroy
122
+ ```
123
+
124
+ ## Contributing
125
+
126
+ 1. Fork it ( https://github.com/hiroponz/neo4r/fork )
127
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
128
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
129
+ 4. Push to the branch (`git push origin my-new-feature`)
130
+ 5. Create a new Pull Request
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,20 @@
1
+ require "active_model"
2
+ require "active_support"
3
+ require "active_support/core_ext"
4
+ require "neography"
5
+
6
+ require "neo4r/attributes"
7
+ require "neo4r/index_config_loader"
8
+ require "neo4r/node"
9
+ require "neo4r/node_traverser"
10
+ require "neo4r/paginated"
11
+ require "neo4r/relation"
12
+ require "neo4r/relationship"
13
+ require "neo4r/relationship_traverser"
14
+ require "neo4r/rest_wrapper"
15
+ require "neo4r/version"
16
+ require "neo4r/will_paginate"
17
+
18
+ module Neo4r
19
+ # Your code goes here...
20
+ end
@@ -0,0 +1,68 @@
1
+ require "neo4r/type_converters"
2
+
3
+ module Neo4r
4
+ # Neo4r node attributes module
5
+ module Attributes
6
+ extend ActiveSupport::Concern
7
+
8
+ # class methods
9
+ module ClassMethods
10
+ # @return [Hash] a hash of all properties and its configuration defined by
11
+ # property class method
12
+ def decl_props
13
+ @decl_props ||= {}
14
+ end
15
+
16
+ # make sure the inherited classes inherit the <tt>_decl_props</tt> hash
17
+ def inherited(klass)
18
+ klass.instance_variable_set(:@decl_props, decl_props.clone)
19
+ super
20
+ end
21
+
22
+ def property(*args)
23
+ options = args.extract_options!
24
+ args.each do |property_sym|
25
+ property_setup(property_sym, options)
26
+ end
27
+ end
28
+
29
+ def to_ruby(hash)
30
+ ret = {}
31
+ hash.each do |k, v|
32
+ if decl_props.key?(k.to_sym)
33
+ ret[k] = decl_props[k.to_sym][:converter].to_ruby(v)
34
+ else
35
+ ret[k] = v
36
+ end
37
+ end
38
+ ret
39
+ end
40
+
41
+ def to_java(hash)
42
+ ret = {}
43
+ hash.each do |k, v|
44
+ if decl_props.key?(k.to_sym)
45
+ ret[k] = decl_props[k.to_sym][:converter].to_java(v)
46
+ elsif v
47
+ ret[k] = v
48
+ end
49
+ end
50
+ ret
51
+ end
52
+
53
+ protected
54
+
55
+ def property_setup(property, options)
56
+ decl_props[property] = options
57
+ handle_property_options_for(property, options)
58
+ end
59
+
60
+ def handle_property_options_for(property, options)
61
+ converter = options[:converter] ||
62
+ Neo4r::TypeConverters
63
+ .converter(decl_props[property][:type])
64
+ decl_props[property][:converter] = converter
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,68 @@
1
+ require "neo4r/relation"
2
+
3
+ module Neo4r
4
+ # Neo4r Finder module
5
+ module Finder
6
+ def find(neo_id)
7
+ rest = RestWrapper.new
8
+ node = rest.get_node(neo_id)
9
+ new(node)
10
+ end
11
+
12
+ def find_by_query(query)
13
+ rest = RestWrapper.new
14
+ ret = rest.execute_query(query)
15
+ ret["data"].map do |data|
16
+ cols = []
17
+ data.each do |col|
18
+ cols << new(col)
19
+ end
20
+ if cols.size == 1
21
+ cols.first
22
+ else
23
+ cols
24
+ end
25
+ end
26
+ end
27
+
28
+ def labels(*labels)
29
+ relation.labels(*labels)
30
+ end
31
+
32
+ def where(hash)
33
+ relation.where(hash)
34
+ end
35
+
36
+ def asc(*props)
37
+ relation.asc(*props)
38
+ end
39
+
40
+ def desc(*props)
41
+ relation.desc(*props)
42
+ end
43
+
44
+ def limit(n)
45
+ relation.limit(n)
46
+ end
47
+
48
+ def offset(n)
49
+ relation.offset(n)
50
+ end
51
+
52
+ def all
53
+ relation.all
54
+ end
55
+
56
+ def first
57
+ relation.first
58
+ end
59
+
60
+ def count
61
+ relation.count
62
+ end
63
+
64
+ def relation
65
+ Relation.new(self)
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+ module Neo4r
3
+ module IndexConfigLoader
4
+ #
5
+ # Load index config from database.
6
+ #
7
+ class << self
8
+ # entry point.
9
+ def load_index_config(mod)
10
+ if ExperimentKlass.table_exists?
11
+ ExperimentKlass.all.each do |klass|
12
+ klass.props.each do |prop|
13
+ prop_key = prop.mnemonic.to_sym
14
+ if prop.is_a?(Property::String)
15
+ mod.index prop_key, field_type: String
16
+ elsif prop.is_a?(Property::Number)
17
+ mod.index prop_key, field_type: Float
18
+ elsif prop.is_a?(Property::Date)
19
+ mod.index prop_key, field_type: Date
20
+ elsif prop.is_a?(Property::DateTime)
21
+ mod.index prop_key, field_type: DateTime
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ def included(mod)
29
+ load_index_config(mod)
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,54 @@
1
+ require "neo4r/finder"
2
+ require "neo4r/property_container"
3
+ require "neo4r/node_relationship"
4
+
5
+ module Neo4r
6
+ # Neo4r Node class
7
+ class Node < PropertyContainer
8
+ extend Finder
9
+ include ActiveModel::Conversion
10
+ include NodeRelationship
11
+
12
+ property :created_at, type: DateTime
13
+ property :updated_at, type: DateTime
14
+
15
+ def self.create(args)
16
+ node = new(args)
17
+ if node.save
18
+ node
19
+ else
20
+ nil
21
+ end
22
+ end
23
+
24
+ def labels
25
+ self.class.name.split("::")
26
+ end
27
+
28
+ def labels=(labels)
29
+ fail "Can not change label!"
30
+ end
31
+
32
+ def save
33
+ time = DateTime.now
34
+ @table[:created_at] = time if is_new?
35
+ @table[:updated_at] = time
36
+ data = self.class.to_java(@table)
37
+ if is_new?
38
+ node = rest.create_node(data)
39
+ @neo_id = node["self"].split("/").last.to_i
40
+ else
41
+ rest.reset_node_properties(@neo_id, data)
42
+ end
43
+ rest.set_label(@neo_id, labels)
44
+ true
45
+ end
46
+
47
+ def destroy
48
+ rest.delete_node!(@neo_id)
49
+ @neo_id = nil
50
+ @table = {}
51
+ true
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,39 @@
1
+ require "neo4r/node_traverser"
2
+ require "neo4r/relationship_traverser"
3
+
4
+ module Neo4r
5
+ # Node relationship module
6
+ module NodeRelationship
7
+ DIRECTIONS = %W(incoming, in, outgoing, out, all, both)
8
+
9
+ def outgoing(types = nil)
10
+ NodeTraverser.new(self).outgoing(types)
11
+ end
12
+
13
+ def incoming(types = nil)
14
+ NodeTraverser.new(self).incoming(types)
15
+ end
16
+
17
+ def both(types = nil)
18
+ NodeTraverser.new(self).both(types)
19
+ end
20
+
21
+ def rels(*types)
22
+ RelationshipTraverser.new(self, types, :both)
23
+ end
24
+
25
+ def rel(dir, type)
26
+ rel = RelationshipTraverser.new(self, type, dir)
27
+ rel = rel.first unless rel.empty?
28
+ rel
29
+ end
30
+
31
+ def rel?(dir = nil, type = nil)
32
+ if DIRECTIONS.include?(dir.to_s)
33
+ !rest.get_node_relationships(self, dir, type).empty?
34
+ else
35
+ !rest.get_node_relationships(self, type, dir).empty?
36
+ end
37
+ end
38
+ end
39
+ end