neomirror 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ab74e8c31f0b8ea8c07d4fdb8b454f7f1823c37b
4
- data.tar.gz: 465c276d4c825cf27d2bf38decb2955287958669
3
+ metadata.gz: 91d4c19efa74a09c812dfbffc777ebb884f3289c
4
+ data.tar.gz: 06e831911c25f4022c41038d5af73d1ca20085e6
5
5
  SHA512:
6
- metadata.gz: 3d952da8b37fd49abd4cf9207992319a39c30f428cda953749e5d1c4cde0d5ece314edb849c39f472a44276c079b260221198ce501b472d8e5578165820a1034
7
- data.tar.gz: 0e96b273a81c88048c053e8d450dd40b949845e306b5e31779b37f869bc2863337c3932776ec9e2d974087bb789ac84a866b7237cc58a6f941e42a80d25bd0b8
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). But it is probably not needed.
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.node_primary_key = :code
192
+ self.neo_primary_key = :code
180
193
 
181
194
  mirror_neo_node
182
195
  end
@@ -23,10 +23,10 @@ module Neomirror::Node
23
23
  @neo_mirror
24
24
  end
25
25
 
26
- def node_primary_key
27
- @node_primary_key ||= self.respond_to?(:primary_key) ? self.__send__(:primary_key) : :id
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 :node_primary_key
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
- neo_node_properties = ::Hash.new
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 do |property, rule|
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
- neo_node_properties
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.node_primary_key)
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
- m[:type] = (m[:type] ? m[:type] : self.name.gsub(/^.*::/, '').gsub(/([a-z\d])([A-Z])/, '\1_\2').upcase).to_sym
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({}) { |h, (property, rule)| h[property] = rule.call(self); h }
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 (m1 = self.__send__(rel_mirror[:start_node])) && (m2 = self.__send__(rel_mirror[:end_node])) &&
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 self.__send__(rel_mirror[:start_node]) && self.__send__(rel_mirror[:end_node]) &&
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], self.__send__(rel_mirror[:start_node]).neo_node,
68
- self.__send__(rel_mirror[:end_node]).neo_node, neo_relationship_properties(rel_mirror))
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
- ::Neomirror.neo.delete_relationship(@neo_rel) if find_neo_relationship(rel_mirror)
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
@@ -1,3 +1,3 @@
1
1
  module Neomirror
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -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
@@ -61,7 +61,7 @@ describe Neomirror::Node do
61
61
  end
62
62
  end
63
63
 
64
- describe ".node_primary_key" do
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)')
@@ -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
- has_many :users, through: :staff
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
@@ -2,7 +2,7 @@ class Postcode
2
2
  attr_accessor :code
3
3
  include Neomirror::Node
4
4
 
5
- self.node_primary_key = :code
5
+ self.neo_primary_key = :code
6
6
 
7
7
  mirror_neo_node
8
8
  end
@@ -1,9 +1,7 @@
1
1
  class Premises < ActiveRecord::Base
2
2
  include Neomirror::Node
3
3
  has_many :memberships
4
- has_many :groups, through: :memberships
5
4
  has_many :staff
6
- has_many :users, through: :staff
7
5
 
8
6
  mirror_neo_node
9
7
  end
data/spec/support/user.rb CHANGED
@@ -1,8 +1,6 @@
1
1
  class User < ActiveRecord::Base
2
2
  include Neomirror::Node
3
3
  has_many :staff
4
- has_many :premises, through: :staff
5
- has_many :groups, through: :staff
6
4
 
7
5
  mirror_neo_node do
8
6
  property :name
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.1
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-06-30 00:00:00.000000000 Z
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