lexster 0.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.
@@ -0,0 +1,28 @@
1
+ module Lexster
2
+ class SearchSession
3
+ def initialize(response, *models)
4
+ @response = response || []
5
+ @models = models
6
+ end
7
+
8
+ def hits
9
+ @response.map { |x| Neography::Node.new(x) }
10
+ end
11
+
12
+ def ids
13
+ @response.collect { |x| x['data']['ar_id'] }
14
+ end
15
+
16
+ def results
17
+ models_by_name = @models.inject({}) { |all, curr| all[curr.name] = curr; all }
18
+
19
+ ids_by_klass = @response.inject({}) do |all, curr|
20
+ klass_name = curr['data']['ar_type']
21
+ (all[models_by_name[klass_name]] ||= []) << curr['data']['ar_id']
22
+ all
23
+ end
24
+
25
+ ids_by_klass.map { |klass, ids| klass.where(id: ids) }.flatten
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,3 @@
1
+ module Lexster
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,170 @@
1
+ require 'spec_helper'
2
+
3
+ describe Lexster::ModelAdditions do
4
+ context "promises" do
5
+ it "should run scripts in a batch and return results" do
6
+ Lexster.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
+ Lexster.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
+ Lexster.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 = Lexster.db.create_node
38
+ node_2 = Lexster.db.create_node
39
+ rel = Lexster.db.create_relationship(:related, node_1, node_2)
40
+
41
+ Lexster.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
+ Lexster.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 = Lexster.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 = Lexster.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 = Lexster.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
+ # Lexster.db.get_node(u1_node_id).should_not be_nil
120
+ # Lexster.db.get_node(u2_node_id).should_not be_nil
121
+ # end
122
+
123
+ # res.length.should == 2
124
+
125
+ # Lexster.db.get_node(u1_node_id).should be_nil
126
+ # Lexster.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 = Lexster.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 = Lexster.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
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Lexster::Config do
4
+ context "config" do
5
+ it "should store and read config" do
6
+ Lexster.configure do |config|
7
+ config.enable_subrefs = false
8
+ end
9
+
10
+ Lexster.config.enable_subrefs.should == false
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+ require 'fileutils'
3
+
4
+
5
+ describe Lexster::ModelConfig do
6
+ context "config on a model" do
7
+ it "should store search fields" do
8
+ Article.lexster_config.search_options.should_not be_nil
9
+ Article.lexster_config.search_options.index_fields.keys.should =~ [ :title, :body, :year ]
10
+ end
11
+
12
+ it "should store stored fields" do
13
+ Article.lexster_config.stored_fields.should_not be_nil
14
+ Article.lexster_config.stored_fields.keys.should =~ [ :title, :year, :title_length ]
15
+ Article.lexster_config.stored_fields[:title_length].should be_a(Proc)
16
+ end
17
+
18
+ it "should store stored fields based on blocks" do
19
+ article = Article.create! title: "Hello", year: 2012
20
+
21
+ article.neo_node.title_length.should == article.title.length
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,131 @@
1
+ require 'spec_helper'
2
+
3
+ describe Lexster::Node do
4
+ context "create graph nodes" do
5
+ it "should call neo_save after model creation" do
6
+ user = User.new(name: "Elad Ossadon")
7
+ user.should_receive(:neo_save)
8
+ user.save!
9
+ end
10
+
11
+ it "should create a node for user" do
12
+ user = User.create!(name: "Elad Ossadon", slug: "elado")
13
+
14
+ user.neo_node.should_not be_nil
15
+
16
+ user.neo_node.ar_id.should == user.id
17
+ user.neo_node.name.should == user.name
18
+ user.neo_node.slug.should == user.slug
19
+ end
20
+
21
+ it "should create a neo_node for movie" do
22
+ movie = Movie.create!(name: "Memento", slug: "memento-1999", year: 1999)
23
+
24
+ movie.neo_node.should_not be_nil
25
+
26
+ movie.neo_node.ar_id.should == movie.id
27
+ movie.neo_node.name.should == movie.name
28
+ movie.neo_node.year.should == movie.year
29
+ end
30
+ end
31
+
32
+ context "update graph nodes" do
33
+ it "should call neo_save after model update" do
34
+ user = User.create!(name: "Elad Ossadon")
35
+ user.should_receive(:neo_save)
36
+ user.name = "John Doe"
37
+ user.save!
38
+ end
39
+
40
+ it "should update a node after model update" do
41
+ user = User.create!(name: "Elad Ossadon")
42
+ user.neo_node.name.should == "Elad Ossadon"
43
+
44
+ user.name = "John Doe"
45
+ user.save!
46
+
47
+ user.neo_node.name.should == "John Doe"
48
+ end
49
+ end
50
+
51
+ context "find by id" do
52
+ it "should find a neo_node for user" do
53
+ user = User.create!(name: "Elad Ossadon", slug: "elado")
54
+
55
+ user.neo_node.should_not be_nil
56
+ user.neo_find_by_id.should_not be_nil
57
+ end
58
+ end
59
+
60
+ context "no auto_index" do
61
+ it "should not index a node if option :auto_index is set to false" do
62
+ model = NoAutoIndexNode.new(name: "Hello")
63
+ model.should_not_receive(:neo_save)
64
+ model.save!
65
+ end
66
+ end
67
+
68
+ context "subrefs" do
69
+ it "should connect subrefs to reference node" do
70
+ old, Lexster.config.enable_subrefs = Lexster.config.enable_subrefs, true
71
+
72
+ Lexster.send(:initialize_subrefs)
73
+
74
+ begin
75
+ Lexster.ref_node.rel(:outgoing, :users_subref).should_not be_nil
76
+ ensure
77
+ Lexster.config.enable_subrefs = old
78
+ end
79
+ end
80
+
81
+ it "should create a relationship with a subref node" do
82
+ old, Lexster.config.enable_subrefs = Lexster.config.enable_subrefs, true
83
+
84
+ Lexster.send(:initialize_subrefs)
85
+
86
+ begin
87
+ user = User.create!(name: "Elad")
88
+ user.neo_node.rel(:incoming, :users).should_not be_nil
89
+ ensure
90
+ Lexster.config.enable_subrefs = old
91
+ end
92
+ end
93
+
94
+ it "should not create a relationship with a subref node if disabled" do
95
+ old, Lexster.config.enable_subrefs = Lexster.config.enable_subrefs, false
96
+
97
+ begin
98
+ user = User.create!(name: "Elad")
99
+ user.neo_node.rel(:incoming, :users_subref).should be_nil
100
+ ensure
101
+ Lexster.config.enable_subrefs = old
102
+ end
103
+ end
104
+ end
105
+
106
+ context "per_model_indexes" do
107
+ it "should create a relationship with a subref node" do
108
+ old, Lexster.config.enable_per_model_indexes = Lexster.config.enable_per_model_indexes, true
109
+
110
+ Lexster.send(:initialize_per_model_indexes)
111
+
112
+ begin
113
+ user = User.create!(name: "Elad")
114
+ Lexster.db.get_node_index(User.neo_model_index_name, 'ar_id', user.id).should_not be_nil
115
+ ensure
116
+ Lexster.config.enable_per_model_indexes = old
117
+ end
118
+ end
119
+
120
+ it "should not create a relationship with a subref node if disabled" do
121
+ old, Lexster.config.enable_per_model_indexes = Lexster.config.enable_per_model_indexes, false
122
+
123
+ begin
124
+ user = User.create!(name: "Elad")
125
+ expect { Lexster.db.get_node_index(User.neo_model_index_name, 'ar_id', user.id) }.to raise_error(Neography::NotFoundException)
126
+ ensure
127
+ Lexster.config.enable_per_model_indexes = old
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,102 @@
1
+ require 'spec_helper'
2
+
3
+ describe Lexster::Relationship do
4
+ let(:user) { User.create!(name: "Elad Ossadon", slug: "elado") }
5
+ let(:movie) { Movie.create!(name: "Memento", slug: "memento-1999", year: 1999) }
6
+
7
+ it "should call neo_save after relationship model creation" do
8
+ Like.any_instance.should_receive(:neo_save)
9
+ user.like! movie
10
+ end
11
+
12
+ it "should create a neo_relationship for like" do
13
+ like = user.like! movie
14
+ like = user.likes.last
15
+
16
+ like.neo_find_by_id.should_not be_nil
17
+
18
+ like.neo_relationship.should_not be_nil
19
+
20
+ like.neo_relationship.start_node.should == user.neo_node
21
+ like.neo_relationship.end_node.should == movie.neo_node
22
+ like.neo_relationship.rel_type.should == 'likes'
23
+ end
24
+
25
+ it "should delete a relationship on deleting a record" do
26
+ user.like! movie
27
+ like = user.likes.last
28
+
29
+ relationship_neo_id = like.neo_relationship.neo_id
30
+
31
+ Neography::Relationship.load(relationship_neo_id).should_not be_nil
32
+
33
+ user.unlike! movie
34
+
35
+ expect { Neography::Relationship.load(relationship_neo_id) }.to raise_error(Neography::RelationshipNotFoundException)
36
+ end
37
+
38
+ it "should update neo4j on manual set of a collection" do
39
+ movies = [
40
+ Movie.create(name: "Memento"),
41
+ Movie.create(name: "The Prestige"),
42
+ Movie.create(name: "The Dark Knight"),
43
+ Movie.create(name: "Spiderman")
44
+ ]
45
+
46
+ user.neo_node.outgoing(:likes).length.should == 0
47
+
48
+ expect {
49
+ user.movies = movies
50
+ }.to change{ user.neo_node.outgoing(:likes).length }.to(movies.length)
51
+
52
+ expect { expect {
53
+ user.movies -= movies[0..1]
54
+ }.to change{ user.movies.count }.by(-2)
55
+ }.to change{ user.neo_node.outgoing(:likes).length }.by(-2)
56
+
57
+ expect {
58
+ user.movies = []
59
+ }.to change{ user.neo_node.outgoing(:likes).length }.to(0)
60
+
61
+ expect {
62
+ user.movie_ids = movies[0...2].collect(&:id)
63
+ }.to change{ user.neo_node.outgoing(:likes).length }.to(2)
64
+ end
65
+
66
+ it "should update a relationship after relationship model update" do
67
+ like = user.like! movie
68
+
69
+ like.neo_relationship.rate.should be_nil
70
+
71
+ like.rate = 10
72
+ like.save!
73
+
74
+ like.neo_relationship.rate.should == 10
75
+ end
76
+
77
+ context "polymorphic relationship" do
78
+ let(:user) { User.create(name: "Elad Ossadon", slug: "elado") }
79
+
80
+ it "should create relationships with polymorphic items" do
81
+ followed = [
82
+ User.create(name: "Some One", slug: "someone"),
83
+ Movie.create(name: "The Prestige"),
84
+ Movie.create(name: "The Dark Knight")
85
+ ]
86
+
87
+ expect {
88
+ followed.each do |item|
89
+ user.user_follows.create!(item: item)
90
+ end
91
+ }.to change{ user.neo_node.outgoing(:follows).length }.to(followed.length)
92
+
93
+ expect {
94
+ user.user_follows = user.user_follows[0...1]
95
+ }.to change{ user.neo_node.outgoing(:follows).length }.to(1)
96
+
97
+ expect {
98
+ user.user_follows = []
99
+ }.to change{ user.neo_node.outgoing(:follows).length }.to(0)
100
+ end
101
+ end
102
+ end