neomirror 0.0.1 → 0.0.2
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.
- checksums.yaml +4 -4
- data/README.md +16 -3
- data/lib/neomirror/node.rb +7 -14
- data/lib/neomirror/relationship.rb +25 -9
- data/lib/neomirror/version.rb +1 -1
- data/spec/neomirror/neomirror_spec.rb +25 -0
- data/spec/neomirror/node_spec.rb +1 -7
- data/spec/neomirror/relationship_spec.rb +7 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/support/group.rb +3 -2
- data/spec/support/postcode.rb +1 -1
- data/spec/support/premises.rb +0 -2
- data/spec/support/user.rb +0 -2
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 91d4c19efa74a09c812dfbffc777ebb884f3289c
|
4
|
+
data.tar.gz: 06e831911c25f4022c41038d5af73d1ca20085e6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 171520bb5e991c0605a03d5adb5d8774e16cf31bc494c8f8e4beb635505af69038be2881831a84d78bd2b7b1610897d7d61a7f8956c1b05e0caeb59f9118fd2b
|
7
|
+
data.tar.gz: 13de4c46626309fd61fc6046156a405909e9805a67039ae0a7f8804fe43d1d063338f9b50b904e2b5846e1bd93cf1738ad3b30dde3dcf8c3cecf8e6bf1dce8c9
|
data/README.md
CHANGED
@@ -163,7 +163,20 @@ class Staff < ActiveRecord::Base
|
|
163
163
|
end
|
164
164
|
```
|
165
165
|
|
166
|
-
Even possible reflect model as node (vertex) and relation(s) (edge).
|
166
|
+
Even possible reflect model as node (vertex) and relation(s) (edge).
|
167
|
+
|
168
|
+
```ruby
|
169
|
+
class Group < ActiveRecord::Base
|
170
|
+
include Neomirror::Node
|
171
|
+
include Neomirror::Relationship
|
172
|
+
|
173
|
+
belongs_to :parent, class_name: 'Group', foreign_key: :parent_id
|
174
|
+
|
175
|
+
mirror_neo_node
|
176
|
+
|
177
|
+
mirror_neo_relationship start_node: :self, end_node: :parent, type: :CHILD_OF
|
178
|
+
end
|
179
|
+
```
|
167
180
|
|
168
181
|
## Compatibility
|
169
182
|
|
@@ -171,12 +184,12 @@ It is possible to use it outside of ActiveRecord (there is no dependency). Just
|
|
171
184
|
|
172
185
|
Also specify primary key attribute if it is differ from `id` and class don't `respond_to? :primary_key` method.
|
173
186
|
|
174
|
-
```
|
187
|
+
```ruby
|
175
188
|
class Postcode
|
176
189
|
attr_accessor :code
|
177
190
|
include Neomirror::Node
|
178
191
|
|
179
|
-
self.
|
192
|
+
self.neo_primary_key = :code
|
180
193
|
|
181
194
|
mirror_neo_node
|
182
195
|
end
|
data/lib/neomirror/node.rb
CHANGED
@@ -23,10 +23,10 @@ module Neomirror::Node
|
|
23
23
|
@neo_mirror
|
24
24
|
end
|
25
25
|
|
26
|
-
def
|
27
|
-
@
|
26
|
+
def neo_primary_key
|
27
|
+
@neo_primary_key ||= self.respond_to?(:primary_key) ? self.__send__(:primary_key) : :id
|
28
28
|
end
|
29
|
-
attr_writer :
|
29
|
+
attr_writer :neo_primary_key
|
30
30
|
end
|
31
31
|
|
32
32
|
def neo_node
|
@@ -36,20 +36,17 @@ module Neomirror::Node
|
|
36
36
|
alias_method :node, :neo_node
|
37
37
|
|
38
38
|
def neo_node_properties
|
39
|
-
|
40
|
-
neo_node_properties[:id] = self.__send__(self.class.node_primary_key)
|
39
|
+
hash = { :id => self.__send__(self.class.neo_primary_key) }
|
41
40
|
if self.class.neo_mirror && self.class.neo_mirror[:properties]
|
42
|
-
self.class.neo_mirror[:properties].each
|
43
|
-
neo_node_properties[property] = rule.call(self)
|
44
|
-
end
|
41
|
+
self.class.neo_mirror[:properties].each { |property, rule| hash[property] = rule.call(self) }
|
45
42
|
end
|
46
|
-
|
43
|
+
hash
|
47
44
|
end
|
48
45
|
|
49
46
|
def find_neo_node
|
50
47
|
raise "Couldn't find neo_node declaration" unless self.class.neo_mirror
|
51
48
|
label = self.class.neo_mirror[:label]
|
52
|
-
id = self.__send__(self.class.
|
49
|
+
id = self.__send__(self.class.neo_primary_key)
|
53
50
|
return nil unless node = ::Neomirror.neo.find_nodes_labeled(label, { :id => id }).first
|
54
51
|
@neo_node = ::Neography::Node.load(node, ::Neomirror.neo)
|
55
52
|
end
|
@@ -76,8 +73,4 @@ module Neomirror::Node
|
|
76
73
|
::Neomirror.neo.delete_node!(@neo_node)
|
77
74
|
true
|
78
75
|
end
|
79
|
-
|
80
|
-
def neo_node_to_cypher
|
81
|
-
":#{self.class.neo_mirror[:label]} {id:#{self.__send__(self.class.node_primary_key)}}"
|
82
|
-
end
|
83
76
|
end
|
@@ -30,11 +30,19 @@ module Neomirror::Relationship
|
|
30
30
|
raise ArgumentError, "Options :start_node and :end_node are mandatory" unless m[:start_node] && m[:end_node]
|
31
31
|
m[:start_node] = m[:start_node].to_sym
|
32
32
|
m[:end_node] = m[:end_node].to_sym
|
33
|
-
|
33
|
+
class_name = self.name.gsub(/^.*::/, '').gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
34
|
+
m[:type] = (m[:type] ? m[:type] : class_name.upcase).to_sym
|
34
35
|
m[:properties] = Neomirror::PropertyCollector.new(&block).properties if block_given?
|
35
36
|
m[:if] = m[:if].to_proc if m[:if]
|
37
|
+
m[:index_name] = "#{m[:start_node] == :self ? class_name.downcase : m[:start_node]}_#{m[:type]}_#{m[:end_node] == :self ? class_name.downcase : m[:end_node]}"
|
38
|
+
::Neomirror.neo.create_relationship_index(m[:index_name])
|
36
39
|
rel_mirrors << m
|
37
40
|
end
|
41
|
+
|
42
|
+
def neo_primary_key
|
43
|
+
@neo_primary_key ||= self.respond_to?(:primary_key) ? self.__send__(:primary_key) : :id
|
44
|
+
end
|
45
|
+
attr_writer :neo_primary_key
|
38
46
|
end
|
39
47
|
|
40
48
|
def neo_relationship(partial_mirror = nil)
|
@@ -45,7 +53,7 @@ module Neomirror::Relationship
|
|
45
53
|
def neo_relationship_properties(partial_mirror = nil)
|
46
54
|
raise "Couldn't find neo_relationship declaration" unless rel_mirror = self.class.rel_mirror(partial_mirror)
|
47
55
|
return nil unless rel_mirror[:properties]
|
48
|
-
rel_mirror[:properties].reduce({}) { |
|
56
|
+
rel_mirror[:properties].reduce({}) { |hash, (property, rule)| hash[property] = rule.call(self); hash }
|
49
57
|
end
|
50
58
|
|
51
59
|
def neo_relationship_must_exist?(partial_mirror = nil)
|
@@ -55,25 +63,30 @@ module Neomirror::Relationship
|
|
55
63
|
|
56
64
|
def find_neo_relationship(partial_mirror = nil)
|
57
65
|
raise "Couldn't find neo_relationship declaration" unless rel_mirror = self.class.rel_mirror(partial_mirror)
|
58
|
-
return nil unless
|
59
|
-
(rel = ::Neomirror.neo.execute_query("MATCH (#{m1.neo_node_to_cypher})-[r:#{rel_mirror[:type]}]->(#{m2.neo_node_to_cypher}) RETURN r")["data"].first)
|
66
|
+
return nil unless rel = ::Neomirror.neo.get_relationship_index(rel_mirror[:index_name], :id, self.__send__(self.class.neo_primary_key))
|
60
67
|
@neo_rel = ::Neography::Relationship.load(rel, ::Neomirror.neo)
|
61
68
|
end
|
62
69
|
|
63
70
|
def create_neo_relationship(partial_mirror = nil)
|
64
71
|
raise "Couldn't find neo_relationship declaration" unless rel_mirror = self.class.rel_mirror(partial_mirror)
|
65
|
-
return nil unless
|
72
|
+
return nil unless (m1 = related_object(rel_mirror[:start_node])) && (m2 = related_object(rel_mirror[:end_node])) &&
|
66
73
|
neo_relationship_must_exist?(rel_mirror)
|
67
|
-
::Neography::Relationship.create(rel_mirror[:type],
|
68
|
-
|
74
|
+
@neo_rel = ::Neography::Relationship.create(rel_mirror[:type], m1.neo_node, m2.neo_node, neo_relationship_properties(rel_mirror))
|
75
|
+
::Neomirror.neo.add_relationship_to_index(rel_mirror[:index_name], :id, self.__send__(self.class.neo_primary_key), @neo_rel)
|
76
|
+
@neo_rel
|
77
|
+
end
|
78
|
+
|
79
|
+
def related_object(method_name)
|
80
|
+
method_name == :self ? self : self.__send__(method_name)
|
69
81
|
end
|
70
82
|
|
71
83
|
def update_neo_relationship(partial_mirror = nil)
|
72
84
|
raise "Couldn't find neo_relationship declaration" unless rel_mirror = self.class.rel_mirror(partial_mirror)
|
73
85
|
if find_neo_relationship(rel_mirror)
|
74
|
-
if neo_relationship_must_exist?(rel_mirror)
|
86
|
+
if related_object(rel_mirror[:start_node]) && related_object(rel_mirror[:end_node]) && neo_relationship_must_exist?(rel_mirror)
|
75
87
|
::Neomirror.neo.reset_relationship_properties(@neo_rel, neo_relationship_properties(rel_mirror))
|
76
88
|
else
|
89
|
+
::Neomirror.neo.remove_relationship_from_index(rel_mirror[:index_name], :id, self.__send__(self.class.neo_primary_key), @neo_rel)
|
77
90
|
::Neomirror.neo.delete_relationship(@neo_rel)
|
78
91
|
end
|
79
92
|
else
|
@@ -83,7 +96,10 @@ module Neomirror::Relationship
|
|
83
96
|
|
84
97
|
def destroy_neo_relationship(partial_mirror = nil)
|
85
98
|
raise "Couldn't find neo_relationship declaration" unless rel_mirror = self.class.rel_mirror(partial_mirror)
|
86
|
-
|
99
|
+
if find_neo_relationship(rel_mirror)
|
100
|
+
::Neomirror.neo.remove_relationship_from_index(rel_mirror[:index_name], :id, self.__send__(self.class.neo_primary_key), @neo_rel)
|
101
|
+
::Neomirror.neo.delete_relationship(@neo_rel)
|
102
|
+
end
|
87
103
|
end
|
88
104
|
|
89
105
|
def create_neo_relationships
|
data/lib/neomirror/version.rb
CHANGED
@@ -0,0 +1,25 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Neomirror do
|
4
|
+
describe "Reflection of model as node and relation" do
|
5
|
+
let(:group) { create(:group) }
|
6
|
+
let(:child_group) { create(:group, parent: group) }
|
7
|
+
|
8
|
+
it "creates neo4j nodes" do
|
9
|
+
group.find_neo_node.should be_a Neography::Node
|
10
|
+
child_group.find_neo_node.should be_a Neography::Node
|
11
|
+
end
|
12
|
+
|
13
|
+
it "creates neo4j relation with object itself" do
|
14
|
+
group.find_neo_relationship.should be_nil
|
15
|
+
child_group.find_neo_relationship.should be_a Neography::Relationship
|
16
|
+
Neomirror.neo.execute_query("MATCH (:Group {id: #{child_group.id}})-[r:CHILD_OF]->(:Group {id: #{group.id}}) RETURN r")["data"].first.should be_present
|
17
|
+
end
|
18
|
+
|
19
|
+
it "destroys relationship on update if actual relationship disappears (both nodes must be present)" do
|
20
|
+
child_group.update(parent_id: nil)
|
21
|
+
child_group.find_neo_relationship.should be_nil
|
22
|
+
Neomirror.neo.execute_query("MATCH (:Group {id: #{child_group.id}})-[r:CHILD_OF]->(:Group {id: #{group.id}}) RETURN r")["data"].first.should be_nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/spec/neomirror/node_spec.rb
CHANGED
@@ -61,7 +61,7 @@ describe Neomirror::Node do
|
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
-
describe ".
|
64
|
+
describe ".neo_primary_key" do
|
65
65
|
let(:postcode) { Postcode.new.tap { |p| p.code = 'ABC' } }
|
66
66
|
|
67
67
|
it "sets custom primary key" do
|
@@ -69,10 +69,4 @@ describe Neomirror::Node do
|
|
69
69
|
postcode.neo_node.id.should == 'ABC'
|
70
70
|
end
|
71
71
|
end
|
72
|
-
|
73
|
-
describe "#neo_node_to_cypher" do
|
74
|
-
it "represents node as cypher element" do
|
75
|
-
user.neo_node_to_cypher.should == ":User {id:#{user.id}}"
|
76
|
-
end
|
77
|
-
end
|
78
72
|
end
|
@@ -92,6 +92,13 @@ describe Neomirror::Relationship do
|
|
92
92
|
staff.find_neo_relationship(type: :VISITOR_OF).should be_nil
|
93
93
|
staff.find_neo_relationship(type: :MANAGER_OF).should be_a Neography::Relationship
|
94
94
|
end
|
95
|
+
|
96
|
+
it "destroys relationship on update if actual relationship disappears (both nodes must be present)" do
|
97
|
+
staff_of_premises
|
98
|
+
Neomirror.neo.execute_query("MATCH (:User {id: #{user.id}})-[r:STAFF_OF]->(:Premises {id: #{premises.id}}) RETURN r")["data"].first.should be_present
|
99
|
+
staff_of_premises.update(premises_id: nil)
|
100
|
+
Neomirror.neo.execute_query("MATCH (:User {id: #{user.id}})-[r:STAFF_OF]->(:Premises {id: #{premises.id}}) RETURN r")["data"].first.should be_nil
|
101
|
+
end
|
95
102
|
end
|
96
103
|
|
97
104
|
describe "#destroy_neo_relationship" do
|
data/spec/spec_helper.rb
CHANGED
@@ -8,7 +8,7 @@ ENV['NEO_URL'] ||= "http://127.0.0.1:7474"
|
|
8
8
|
Neomirror.connection = Neography::Rest.new(ENV['NEO_URL'])
|
9
9
|
|
10
10
|
ActiveRecord::Base.connection.execute('CREATE TABLE premises ("id" INTEGER PRIMARY KEY NOT NULL)')
|
11
|
-
ActiveRecord::Base.connection.execute('CREATE TABLE groups ("id" INTEGER PRIMARY KEY NOT NULL)')
|
11
|
+
ActiveRecord::Base.connection.execute('CREATE TABLE groups ("id" INTEGER PRIMARY KEY NOT NULL, "parent_id" INTEGER DEFAULT NULL)')
|
12
12
|
ActiveRecord::Base.connection.execute('CREATE TABLE users ("id" INTEGER PRIMARY KEY NOT NULL, "name" varchar(255) NOT NULL)')
|
13
13
|
ActiveRecord::Base.connection.execute('CREATE TABLE memberships ("id" INTEGER PRIMARY KEY NOT NULL, "premises_id" INTEGER DEFAULT NULL, "group_id" INTEGER DEFAULT NULL)')
|
14
14
|
ActiveRecord::Base.connection.execute('CREATE TABLE staff ("id" INTEGER PRIMARY KEY NOT NULL, "user_id" INTEGER DEFAULT NULL, "premises_id" INTEGER DEFAULT NULL, "group_id" INTEGER DEFAULT NULL, "roles" TEXT)')
|
data/spec/support/group.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
class Group < ActiveRecord::Base
|
2
2
|
include Neomirror::Node
|
3
|
+
include Neomirror::Relationship
|
3
4
|
has_many :memberships
|
4
|
-
has_many :premises, through: :memberships
|
5
5
|
has_many :staff
|
6
|
-
|
6
|
+
belongs_to :parent, class_name: 'Group', foreign_key: :parent_id
|
7
7
|
|
8
8
|
mirror_neo_node
|
9
|
+
mirror_neo_relationship start_node: :self, end_node: :parent, type: :CHILD_OF
|
9
10
|
end
|
data/spec/support/postcode.rb
CHANGED
data/spec/support/premises.rb
CHANGED
data/spec/support/user.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: neomirror
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alex Avoyants
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-07-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: neography
|
@@ -162,6 +162,7 @@ files:
|
|
162
162
|
- spec/factories/premises.rb
|
163
163
|
- spec/factories/staff.rb
|
164
164
|
- spec/factories/user.rb
|
165
|
+
- spec/neomirror/neomirror_spec.rb
|
165
166
|
- spec/neomirror/node_spec.rb
|
166
167
|
- spec/neomirror/relationship_spec.rb
|
167
168
|
- spec/spec_helper.rb
|
@@ -202,6 +203,7 @@ test_files:
|
|
202
203
|
- spec/factories/premises.rb
|
203
204
|
- spec/factories/staff.rb
|
204
205
|
- spec/factories/user.rb
|
206
|
+
- spec/neomirror/neomirror_spec.rb
|
205
207
|
- spec/neomirror/node_spec.rb
|
206
208
|
- spec/neomirror/relationship_spec.rb
|
207
209
|
- spec/spec_helper.rb
|