neoid 0.0.51 → 0.1
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.
- data/CHANGELOG.md +35 -0
- data/README.md +148 -47
- data/TODO.md +0 -2
- data/lib/neoid.rb +90 -13
- data/lib/neoid/batch.rb +168 -0
- data/lib/neoid/config.rb +6 -0
- data/lib/neoid/middleware.rb +4 -2
- data/lib/neoid/model_additions.rb +60 -15
- data/lib/neoid/model_config.rb +2 -0
- data/lib/neoid/node.rb +103 -54
- data/lib/neoid/relationship.rb +88 -53
- data/lib/neoid/version.rb +1 -1
- data/spec/neoid/batch_spec.rb +170 -0
- data/spec/neoid/config_spec.rb +13 -0
- data/spec/neoid/model_additions_spec.rb +111 -17
- data/spec/neoid/search_spec.rb +0 -1
- data/spec/neoid_spec.rb +7 -1
- data/spec/spec_helper.rb +11 -9
- data/spec/support/models.rb +12 -3
- data/spec/support/schema.rb +4 -0
- metadata +8 -2
data/lib/neoid/relationship.rb
CHANGED
@@ -1,59 +1,100 @@
|
|
1
1
|
module Neoid
|
2
2
|
module Relationship
|
3
|
+
# this is a proxy that delays loading of start_node and end_node from Neo4j until accessed.
|
4
|
+
# the original Neography Relatioship loaded them on initialization
|
5
|
+
class RelationshipLazyProxy < ::Neography::Relationship
|
6
|
+
def start_node
|
7
|
+
@start_node_from_db ||= @start_node = Neography::Node.load(@start_node, Neoid.db)
|
8
|
+
end
|
9
|
+
|
10
|
+
def end_node
|
11
|
+
@end_node_from_db ||= @end_node = Neography::Node.load(@end_node, Neoid.db)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.from_hash(hash)
|
16
|
+
relationship = RelationshipLazyProxy.new(hash)
|
17
|
+
|
18
|
+
relationship
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
module ClassMethods
|
23
|
+
def delete_command
|
24
|
+
:delete_relationship
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
3
28
|
module InstanceMethods
|
4
29
|
def neo_find_by_id
|
5
|
-
Neoid.db.
|
6
|
-
|
7
|
-
|
30
|
+
results = Neoid.db.get_relationship_auto_index(Neoid::UNIQUE_ID_KEY, self.neo_unique_id)
|
31
|
+
relationship = results.present? ? Neoid::Relationship.from_hash(results[0]) : nil
|
32
|
+
relationship
|
8
33
|
end
|
9
34
|
|
10
|
-
def
|
35
|
+
def _neo_save
|
11
36
|
return unless Neoid.enabled?
|
12
|
-
@_neo_destroyed = false
|
13
37
|
|
14
38
|
options = self.class.neoid_config.relationship_options
|
15
39
|
|
16
|
-
|
17
|
-
|
40
|
+
start_item = self.send(options[:start_node])
|
41
|
+
end_item = self.send(options[:end_node])
|
18
42
|
|
19
|
-
return unless
|
43
|
+
return unless start_item && end_item
|
44
|
+
|
45
|
+
# initialize nodes
|
46
|
+
start_item.neo_node
|
47
|
+
end_item.neo_node
|
20
48
|
|
21
|
-
data = self.to_neo.merge(ar_type: self.class.name, ar_id: self.id)
|
49
|
+
data = self.to_neo.merge(ar_type: self.class.name, ar_id: self.id, Neoid::UNIQUE_ID_KEY => self.neo_unique_id)
|
22
50
|
data.reject! { |k, v| v.nil? }
|
23
|
-
|
24
|
-
relationship = Neography::Relationship.create(
|
25
|
-
options[:type].is_a?(Proc) ? options[:type].call(self) : options[:type],
|
26
|
-
start_node.neo_node,
|
27
|
-
end_node.neo_node,
|
28
|
-
data
|
29
|
-
)
|
30
|
-
|
31
|
-
Neoid.db.add_relationship_to_index(self.class.neo_index_name, :ar_id, self.id, relationship)
|
32
51
|
|
33
|
-
|
52
|
+
rel_type = options[:type].is_a?(Proc) ? options[:type].call(self) : options[:type]
|
53
|
+
|
54
|
+
gremlin_query = <<-GREMLIN
|
55
|
+
idx = g.idx('relationship_auto_index');
|
56
|
+
q = null;
|
57
|
+
if (idx) q = idx.get(unique_id_key, unique_id);
|
58
|
+
|
59
|
+
relationship = null;
|
60
|
+
if (q && q.hasNext()) {
|
61
|
+
relationship = q.next();
|
62
|
+
relationship_data.each {
|
63
|
+
if (relationship.getProperty(it.key) != it.value) {
|
64
|
+
relationship.setProperty(it.key, it.value);
|
65
|
+
}
|
66
|
+
}
|
67
|
+
} else {
|
68
|
+
node_index = g.idx('node_auto_index');
|
69
|
+
start_node = node_index.get(unique_id_key, start_node_unique_id).next();
|
70
|
+
end_node = node_index.get(unique_id_key, end_node_unique_id).next();
|
71
|
+
|
72
|
+
relationship = g.addEdge(start_node, end_node, rel_type, relationship_data);
|
73
|
+
}
|
74
|
+
|
75
|
+
relationship
|
76
|
+
GREMLIN
|
77
|
+
|
78
|
+
script_vars = {
|
79
|
+
unique_id_key: Neoid::UNIQUE_ID_KEY,
|
80
|
+
relationship_data: data,
|
81
|
+
unique_id: self.neo_unique_id,
|
82
|
+
start_node_unique_id: start_item.neo_unique_id,
|
83
|
+
end_node_unique_id: end_item.neo_unique_id,
|
84
|
+
rel_type: rel_type
|
85
|
+
}
|
86
|
+
|
87
|
+
Neoid::logger.info "Relationship#neo_save #{self.class.name} #{self.id}"
|
34
88
|
|
35
|
-
relationship
|
36
|
-
|
37
|
-
|
38
|
-
def neo_load(relationship)
|
39
|
-
Neography::Relationship.load(relationship)
|
40
|
-
end
|
41
|
-
|
42
|
-
def neo_destroy
|
43
|
-
return if @_neo_destroyed
|
44
|
-
@_neo_destroyed = true
|
45
|
-
return unless neo_relationship
|
46
|
-
Neoid.db.remove_relationship_from_index(self.class.neo_index_name, neo_relationship)
|
47
|
-
neo_relationship.del
|
48
|
-
_reset_neo_representation
|
49
|
-
|
50
|
-
Neoid::logger.info "Relationship#neo_destroy #{self.class.name} #{self.id}, index = #{self.class.neo_index_name}"
|
89
|
+
relationship = Neoid.execute_script_or_add_to_batch gremlin_query, script_vars do |value|
|
90
|
+
Neoid::Relationship.from_hash(value)
|
91
|
+
end
|
51
92
|
|
52
|
-
|
93
|
+
relationship
|
53
94
|
end
|
54
95
|
|
55
|
-
def
|
56
|
-
Neoid.
|
96
|
+
def neo_load(hash)
|
97
|
+
Neoid::Relationship.from_hash(hash)
|
57
98
|
end
|
58
99
|
|
59
100
|
def neo_relationship
|
@@ -64,16 +105,15 @@ module Neoid
|
|
64
105
|
def self.included(receiver)
|
65
106
|
receiver.send :include, Neoid::ModelAdditions
|
66
107
|
receiver.send :include, InstanceMethods
|
108
|
+
receiver.extend ClassMethods
|
67
109
|
|
68
|
-
receiver.
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
Neoid.relationship_models << receiver
|
76
|
-
end
|
110
|
+
initialize_relationship receiver if Neoid.env_loaded
|
111
|
+
|
112
|
+
Neoid.relationship_models << receiver
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.meta_data
|
116
|
+
@meta_data ||= {}
|
77
117
|
end
|
78
118
|
|
79
119
|
def self.initialize_relationship(rel_model)
|
@@ -90,7 +130,6 @@ module Neoid
|
|
90
130
|
# e.g. User has_many :likes, after_remove: ...
|
91
131
|
full_callback_name = "after_remove_for_#{this_has_many.name}"
|
92
132
|
belongs_to.klass.send(full_callback_name) << :neo_after_relationship_remove if belongs_to.klass.method_defined?(full_callback_name)
|
93
|
-
# belongs_to.klass.send(:has_many, this_has_many.name, this_has_many.options.merge(after_remove: :neo_after_relationship_remove))
|
94
133
|
|
95
134
|
# has_many (with through) on the side of the relationship that removes a relationship. e.g. User has_many :movies, through :likes
|
96
135
|
many_to_many = all_has_many.find { |o| o.options[:through] == this_has_many.name }
|
@@ -104,24 +143,20 @@ module Neoid
|
|
104
143
|
# movie_id
|
105
144
|
foreign_key_of_record = many_to_many.source_reflection.foreign_key
|
106
145
|
|
107
|
-
(Neoid.
|
146
|
+
(Neoid::Relationship.meta_data ||= {}).tap do |data|
|
108
147
|
(data[belongs_to.klass.name.to_s] ||= {}).tap do |model_data|
|
109
148
|
model_data[many_to_many.klass.name.to_s] = [rel_model.name.to_s, foreign_key_of_owner, foreign_key_of_record]
|
110
149
|
end
|
111
150
|
end
|
112
151
|
|
113
|
-
# puts Neoid.config[:relationship_meta_data].inspect
|
114
|
-
|
115
152
|
# e.g. User has_many :movies, through: :likes, before_remove: ...
|
116
153
|
full_callback_name = "before_remove_for_#{many_to_many.name}"
|
117
154
|
belongs_to.klass.send(full_callback_name) << :neo_before_relationship_through_remove if belongs_to.klass.method_defined?(full_callback_name)
|
118
|
-
# belongs_to.klass.send(:has_many, many_to_many.name, many_to_many.options.merge(before_remove: :neo_after_relationship_remove))
|
119
155
|
|
120
156
|
|
121
157
|
# e.g. User has_many :movies, through: :likes, after_remove: ...
|
122
158
|
full_callback_name = "after_remove_for_#{many_to_many.name}"
|
123
159
|
belongs_to.klass.send(full_callback_name) << :neo_after_relationship_through_remove if belongs_to.klass.method_defined?(full_callback_name)
|
124
|
-
# belongs_to.klass.send(:has_many, many_to_many.name, many_to_many.options.merge(after_remove: :neo_after_relationship_remove))
|
125
160
|
end
|
126
161
|
end
|
127
162
|
end
|
data/lib/neoid/version.rb
CHANGED
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Neoid::ModelAdditions do
|
4
|
+
context "promises" do
|
5
|
+
it "should run scripts in a batch and return results" do
|
6
|
+
Neoid.batch do |batch|
|
7
|
+
batch << [:execute_script, "1"]
|
8
|
+
batch << [:execute_script, "2"]
|
9
|
+
end.then do |results|
|
10
|
+
results.should == [1, 2]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should run scripts in a batch with batch_size and flush batch when it's full" do
|
15
|
+
Neoid.batch(batch_size: 3) do |batch|
|
16
|
+
(0...9).each do |i|
|
17
|
+
batch.count.should == i % 3
|
18
|
+
batch << [:execute_script, i.to_s]
|
19
|
+
if i % 3 == 0
|
20
|
+
batch.results.count.should == i
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should run scripts in a batch with batch_size and return all results" do
|
27
|
+
Neoid.batch(batch_size: 2) do |batch|
|
28
|
+
(1..6).each do |i|
|
29
|
+
batch << [:execute_script, i.to_s]
|
30
|
+
end
|
31
|
+
end.then do |results|
|
32
|
+
results.should == [1, 2, 3, 4, 5, 6]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should return results then process them" do
|
37
|
+
node_1 = Neoid.db.create_node
|
38
|
+
node_2 = Neoid.db.create_node
|
39
|
+
rel = Neoid.db.create_relationship(:related, node_1, node_2)
|
40
|
+
|
41
|
+
Neoid.batch do |batch|
|
42
|
+
batch << [:execute_script, "g.v(neo_id)", neo_id: node_1['self'].split('/').last.to_i]
|
43
|
+
batch << [:execute_script, "g.v(neo_id)", neo_id: node_2['self'].split('/').last]
|
44
|
+
batch << [:execute_script, "g.e(neo_id)", neo_id: rel['self'].split('/').last]
|
45
|
+
end.then do |results|
|
46
|
+
results[0].should be_a(Neography::Node)
|
47
|
+
results[1].should be_a(Neography::Node)
|
48
|
+
results[2].should be_a(Neography::Relationship)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should remember what to do after each script has executed, and perform it when batch is flushed" do
|
53
|
+
then_results = []
|
54
|
+
|
55
|
+
Neoid.batch do |batch|
|
56
|
+
(batch << [:execute_script, "1"]).then { |res| then_results << res }
|
57
|
+
(batch << [:execute_script, "2"]).then { |res| then_results << res }
|
58
|
+
batch << [:execute_script, "3"]
|
59
|
+
(batch << [:execute_script, "4"]).then { |res| then_results << res }
|
60
|
+
end.then do |results|
|
61
|
+
results.should == [1, 2, 3, 4]
|
62
|
+
then_results.should == [1, 2, 4]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context "nodes" do
|
68
|
+
it "should not execute until batch is done" do
|
69
|
+
u1 = u2 = nil
|
70
|
+
|
71
|
+
res = Neoid.batch do
|
72
|
+
u1 = User.create!(name: "U1")
|
73
|
+
u2 = User.create!(name: "U2")
|
74
|
+
|
75
|
+
u1.neo_find_by_id.should be_nil
|
76
|
+
u2.neo_find_by_id.should be_nil
|
77
|
+
end
|
78
|
+
|
79
|
+
res.length.should == 2
|
80
|
+
|
81
|
+
u1.neo_find_by_id.should_not be_nil
|
82
|
+
u2.neo_find_by_id.should_not be_nil
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should update nodes in batch" do
|
86
|
+
u1 = User.create!(name: "U1")
|
87
|
+
u2 = User.create!(name: "U2")
|
88
|
+
|
89
|
+
res = Neoid.batch do
|
90
|
+
u1.name = "U1 update"
|
91
|
+
u2.name = "U2 update"
|
92
|
+
|
93
|
+
u1.save!
|
94
|
+
u2.save!
|
95
|
+
|
96
|
+
u1.neo_find_by_id.name.should == "U1"
|
97
|
+
u2.neo_find_by_id.name.should == "U2"
|
98
|
+
end
|
99
|
+
|
100
|
+
res.length.should == 2
|
101
|
+
|
102
|
+
u1.neo_find_by_id.name.should == "U1 update"
|
103
|
+
u2.neo_find_by_id.name.should == "U2 update"
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
# Not working yet because Neography can't delete a node and all of its realtionships in a batch, and deleting a node with relationships results an error
|
108
|
+
# it "should delete nodes in batch" do
|
109
|
+
# u1 = User.create!(name: "U1")
|
110
|
+
# u2 = User.create!(name: "U2")
|
111
|
+
|
112
|
+
# res = Neoid.batch do
|
113
|
+
# u1_node_id = u1.neo_find_by_id.neo_id
|
114
|
+
# u2_node_id = u2.neo_find_by_id.neo_id
|
115
|
+
|
116
|
+
# u1.destroy
|
117
|
+
# u2.destroy
|
118
|
+
|
119
|
+
# Neoid.db.get_node(u1_node_id).should_not be_nil
|
120
|
+
# Neoid.db.get_node(u2_node_id).should_not be_nil
|
121
|
+
# end
|
122
|
+
|
123
|
+
# res.length.should == 2
|
124
|
+
|
125
|
+
# Neoid.db.get_node(u1_node_id).should be_nil
|
126
|
+
# Neoid.db.get_node(u2_node_id).should be_nil
|
127
|
+
# end
|
128
|
+
end
|
129
|
+
|
130
|
+
context "relationships" do
|
131
|
+
let(:user) { User.create(name: "Elad Ossadon", slug: "elado") }
|
132
|
+
let(:movie) { Movie.create(name: "Memento", slug: "memento-1999", year: 1999) }
|
133
|
+
|
134
|
+
it "should not execute until batch is done" do
|
135
|
+
# ensure user and movie nodes are inserted
|
136
|
+
user
|
137
|
+
movie
|
138
|
+
|
139
|
+
res = Neoid.batch do |batch|
|
140
|
+
user.like! movie
|
141
|
+
|
142
|
+
user.likes.last.neo_find_by_id.should be_nil
|
143
|
+
end
|
144
|
+
|
145
|
+
res.length.should == 1
|
146
|
+
|
147
|
+
user.likes.last.neo_find_by_id.should_not be_nil
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should not execute until batch is done" do
|
151
|
+
# ensure user and movie nodes are inserted
|
152
|
+
user
|
153
|
+
movie
|
154
|
+
|
155
|
+
# then destroy the nodes, allow the relationship do that in the batch
|
156
|
+
user.neo_destroy
|
157
|
+
movie.neo_destroy
|
158
|
+
|
159
|
+
res = Neoid.batch do |batch|
|
160
|
+
user.like! movie
|
161
|
+
|
162
|
+
user.likes.last.neo_find_by_id.should be_nil
|
163
|
+
end
|
164
|
+
|
165
|
+
res.length.should == 3
|
166
|
+
|
167
|
+
user.likes.last.neo_find_by_id.should_not be_nil
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -1,16 +1,15 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'fileutils'
|
3
2
|
|
4
3
|
describe Neoid::ModelAdditions do
|
5
4
|
context "nodes" do
|
6
5
|
context "create graph nodes" do
|
7
|
-
it "should call
|
8
|
-
User.
|
9
|
-
|
10
|
-
|
6
|
+
it "should call neo_save after model creation" do
|
7
|
+
user = User.new(name: "Elad Ossadon")
|
8
|
+
user.should_receive(:neo_save)
|
9
|
+
user.save!
|
11
10
|
end
|
12
11
|
|
13
|
-
it "should create a
|
12
|
+
it "should create a node for user" do
|
14
13
|
user = User.create!(name: "Elad Ossadon", slug: "elado")
|
15
14
|
|
16
15
|
user.neo_node.should_not be_nil
|
@@ -22,7 +21,7 @@ describe Neoid::ModelAdditions do
|
|
22
21
|
|
23
22
|
it "should create a neo_node for movie" do
|
24
23
|
movie = Movie.create!(name: "Memento", slug: "memento-1999", year: 1999)
|
25
|
-
|
24
|
+
|
26
25
|
movie.neo_node.should_not be_nil
|
27
26
|
|
28
27
|
movie.neo_node.ar_id.should == movie.id
|
@@ -31,26 +30,110 @@ describe Neoid::ModelAdditions do
|
|
31
30
|
end
|
32
31
|
end
|
33
32
|
|
33
|
+
context "update graph nodes" do
|
34
|
+
it "should call neo_save after model update" do
|
35
|
+
user = User.create!(name: "Elad Ossadon")
|
36
|
+
user.should_receive(:neo_save)
|
37
|
+
user.name = "John Doe"
|
38
|
+
user.save!
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should update a node after model update" do
|
42
|
+
user = User.create!(name: "Elad Ossadon")
|
43
|
+
user.neo_node.name.should == "Elad Ossadon"
|
44
|
+
|
45
|
+
user.name = "John Doe"
|
46
|
+
user.save!
|
47
|
+
|
48
|
+
user.neo_node.name.should == "John Doe"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
34
52
|
context "find by id" do
|
35
53
|
it "should find a neo_node for user" do
|
36
54
|
user = User.create!(name: "Elad Ossadon", slug: "elado")
|
37
|
-
|
55
|
+
|
38
56
|
user.neo_node.should_not be_nil
|
39
57
|
user.neo_find_by_id.should_not be_nil
|
40
58
|
end
|
41
59
|
end
|
60
|
+
|
61
|
+
context "no auto_index" do
|
62
|
+
it "should not index a node if option :auto_index is set to false" do
|
63
|
+
model = NoAutoIndexNode.new(name: "Hello")
|
64
|
+
model.should_not_receive(:neo_save)
|
65
|
+
model.save!
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context "subrefs" do
|
70
|
+
it "should create a relationship with a subref node" do
|
71
|
+
old, Neoid.config.enable_subrefs = Neoid.config.enable_subrefs, true
|
72
|
+
|
73
|
+
Neoid.send(:initialize_subrefs)
|
74
|
+
|
75
|
+
begin
|
76
|
+
user = User.create!(name: "Elad")
|
77
|
+
user.neo_node.rel(:incoming, :users_subref).should_not be_nil
|
78
|
+
ensure
|
79
|
+
Neoid.config.enable_subrefs = old
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should not create a relationship with a subref node if disabled" do
|
84
|
+
old, Neoid.config.enable_subrefs = Neoid.config.enable_subrefs, false
|
85
|
+
|
86
|
+
begin
|
87
|
+
user = User.create!(name: "Elad")
|
88
|
+
user.neo_node.rel(:incoming, :users_subref).should be_nil
|
89
|
+
ensure
|
90
|
+
Neoid.config.enable_subrefs = old
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context "per_model_indexes" do
|
96
|
+
it "should create a relationship with a subref node" do
|
97
|
+
old, Neoid.config.enable_per_model_indexes = Neoid.config.enable_per_model_indexes, true
|
98
|
+
|
99
|
+
Neoid.send(:initialize_per_model_indexes)
|
100
|
+
|
101
|
+
begin
|
102
|
+
user = User.create!(name: "Elad")
|
103
|
+
Neoid.db.get_node_index(User.neo_model_index_name, 'ar_id', user.id).should_not be_nil
|
104
|
+
ensure
|
105
|
+
Neoid.config.enable_per_model_indexes = old
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should not create a relationship with a subref node if disabled" do
|
110
|
+
old, Neoid.config.enable_per_model_indexes = Neoid.config.enable_per_model_indexes, false
|
111
|
+
|
112
|
+
begin
|
113
|
+
user = User.create!(name: "Elad")
|
114
|
+
expect { Neoid.db.get_node_index(User.neo_model_index_name, 'ar_id', user.id) }.to raise_error(Neography::NotFoundException)
|
115
|
+
ensure
|
116
|
+
Neoid.config.enable_per_model_indexes = old
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
42
120
|
end
|
43
121
|
|
44
122
|
context "relationships" do
|
45
|
-
let(:user) { User.create(name: "Elad Ossadon", slug: "elado") }
|
46
|
-
let(:movie) { Movie.create(name: "Memento", slug: "memento-1999", year: 1999) }
|
123
|
+
let(:user) { User.create!(name: "Elad Ossadon", slug: "elado") }
|
124
|
+
let(:movie) { Movie.create!(name: "Memento", slug: "memento-1999", year: 1999) }
|
47
125
|
|
48
|
-
it "should
|
126
|
+
it "should call neo_save after relationship model creation" do
|
127
|
+
Like.any_instance.should_receive(:neo_save)
|
49
128
|
user.like! movie
|
50
|
-
|
51
|
-
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should create a neo_relationship for like" do
|
132
|
+
like = user.like! movie
|
133
|
+
like = user.likes.last
|
134
|
+
|
52
135
|
like.neo_find_by_id.should_not be_nil
|
53
|
-
|
136
|
+
|
54
137
|
like.neo_relationship.should_not be_nil
|
55
138
|
|
56
139
|
like.neo_relationship.start_node.should == user.neo_node
|
@@ -63,7 +146,7 @@ describe Neoid::ModelAdditions do
|
|
63
146
|
like = user.likes.last
|
64
147
|
|
65
148
|
relationship_neo_id = like.neo_relationship.neo_id
|
66
|
-
|
149
|
+
|
67
150
|
Neography::Relationship.load(relationship_neo_id).should_not be_nil
|
68
151
|
|
69
152
|
user.unlike! movie
|
@@ -98,12 +181,23 @@ describe Neoid::ModelAdditions do
|
|
98
181
|
user.movie_ids = movies[0...2].collect(&:id)
|
99
182
|
}.to change{ user.neo_node.outgoing(:likes).length }.to(2)
|
100
183
|
end
|
184
|
+
|
185
|
+
it "should update a relationship after relationship model update" do
|
186
|
+
like = user.like! movie
|
187
|
+
|
188
|
+
like.neo_relationship.rate.should be_nil
|
189
|
+
|
190
|
+
like.rate = 10
|
191
|
+
like.save!
|
192
|
+
|
193
|
+
like.neo_relationship.rate.should == 10
|
194
|
+
end
|
101
195
|
end
|
102
196
|
|
103
197
|
context "polymorphic relationship" do
|
104
198
|
let(:user) { User.create(name: "Elad Ossadon", slug: "elado") }
|
105
199
|
|
106
|
-
it "
|
200
|
+
it "should create relationships with polymorphic items" do
|
107
201
|
followed = [
|
108
202
|
User.create(name: "Some One", slug: "someone"),
|
109
203
|
Movie.create(name: "The Prestige"),
|
@@ -112,7 +206,7 @@ describe Neoid::ModelAdditions do
|
|
112
206
|
|
113
207
|
expect {
|
114
208
|
followed.each do |item|
|
115
|
-
user.user_follows.create(item: item)
|
209
|
+
user.user_follows.create!(item: item)
|
116
210
|
end
|
117
211
|
}.to change{ user.neo_node.outgoing(:follows).length }.to(followed.length)
|
118
212
|
|