neoid 0.1.2 → 0.2.0
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 +15 -0
- data/LICENSE +1 -1
- data/README.md +27 -25
- data/Rakefile +2 -2
- data/lib/neoid.rb +74 -61
- data/lib/neoid/batch.rb +27 -27
- data/lib/neoid/database_cleaner.rb +1 -1
- data/lib/neoid/middleware.rb +1 -1
- data/lib/neoid/model_additions.rb +13 -11
- data/lib/neoid/model_config.rb +13 -13
- data/lib/neoid/node.rb +21 -21
- data/lib/neoid/railtie.rb +1 -1
- data/lib/neoid/relationship.rb +78 -78
- data/lib/neoid/search_session.rb +3 -3
- data/lib/neoid/version.rb +1 -1
- data/spec/factories.rb +12 -0
- data/spec/neoid/batch_spec.rb +68 -89
- data/spec/neoid/config_spec.rb +6 -6
- data/spec/neoid/model_config_spec.rb +14 -13
- data/spec/neoid/node_spec.rb +60 -79
- data/spec/neoid/relationship_spec.rb +39 -37
- data/spec/neoid/search_spec.rb +71 -46
- data/spec/neoid_spec.rb +11 -4
- data/spec/spec_helper.rb +23 -4
- data/spec/support/database.yml +1 -1
- data/spec/support/models.rb +16 -16
- data/spec/support/schema.rb +1 -2
- metadata +84 -31
- data/.gitignore +0 -5
- data/.rspec +0 -1
- data/.travis.yml +0 -4
- data/CHANGELOG.md +0 -58
- data/Gemfile +0 -4
- data/TODO.md +0 -4
- data/neoid.gemspec +0 -28
@@ -1,49 +1,50 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Neoid::Relationship do
|
4
|
-
let(:user) { User.create!(name:
|
5
|
-
let(:movie) { Movie.create!(name:
|
6
|
-
|
7
|
-
it
|
8
|
-
Like.
|
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
|
+
expect_any_instance_of(Like).to receive(:neo_save)
|
9
9
|
user.like! movie
|
10
10
|
end
|
11
11
|
|
12
|
-
it
|
12
|
+
it 'should create a neo_relationship for like' do
|
13
13
|
like = user.like! movie
|
14
14
|
like = user.likes.last
|
15
15
|
|
16
|
-
like.neo_find_by_id.
|
16
|
+
expect(like.neo_find_by_id).to_not be_nil
|
17
|
+
|
18
|
+
expect(like.neo_relationship).to_not be_nil
|
17
19
|
|
18
|
-
like.neo_relationship.
|
19
|
-
|
20
|
-
like.neo_relationship.
|
21
|
-
like.neo_relationship.end_node.should == movie.neo_node
|
22
|
-
like.neo_relationship.rel_type.should == 'likes'
|
20
|
+
expect(like.neo_relationship.start_node).to eq(user.neo_node)
|
21
|
+
expect(like.neo_relationship.end_node).to eq(movie.neo_node)
|
22
|
+
expect(like.neo_relationship.rel_type).to eq('likes')
|
23
23
|
end
|
24
|
-
|
25
|
-
it
|
24
|
+
|
25
|
+
it 'should delete a relationship on deleting a record' do
|
26
26
|
user.like! movie
|
27
27
|
like = user.likes.last
|
28
|
-
|
28
|
+
|
29
29
|
relationship_neo_id = like.neo_relationship.neo_id
|
30
30
|
|
31
|
-
Neography::Relationship.load(relationship_neo_id).
|
32
|
-
|
31
|
+
expect(Neography::Relationship.load(relationship_neo_id)).to_not be_nil
|
32
|
+
|
33
33
|
user.unlike! movie
|
34
|
-
|
34
|
+
|
35
35
|
expect { Neography::Relationship.load(relationship_neo_id) }.to raise_error(Neography::RelationshipNotFoundException)
|
36
36
|
end
|
37
37
|
|
38
|
-
it
|
38
|
+
it 'should update neo4j on manual set of a collection' do
|
39
|
+
pending
|
39
40
|
movies = [
|
40
|
-
Movie.create(name:
|
41
|
-
Movie.create(name:
|
42
|
-
Movie.create(name:
|
43
|
-
Movie.create(name:
|
41
|
+
Movie.create(name: 'Memento'),
|
42
|
+
Movie.create(name: 'The Prestige'),
|
43
|
+
Movie.create(name: 'The Dark Knight'),
|
44
|
+
Movie.create(name: 'Spiderman')
|
44
45
|
]
|
45
46
|
|
46
|
-
user.neo_node.outgoing(:likes).length.
|
47
|
+
expect(user.neo_node.outgoing(:likes).length).to eq(0)
|
47
48
|
|
48
49
|
expect {
|
49
50
|
user.movies = movies
|
@@ -59,44 +60,45 @@ describe Neoid::Relationship do
|
|
59
60
|
}.to change{ user.neo_node.outgoing(:likes).length }.to(0)
|
60
61
|
|
61
62
|
expect {
|
62
|
-
user.movie_ids = movies[0...2].
|
63
|
+
user.movie_ids = movies[0...2].map(&:id)
|
63
64
|
}.to change{ user.neo_node.outgoing(:likes).length }.to(2)
|
64
65
|
end
|
65
66
|
|
66
|
-
it
|
67
|
+
it 'should update a relationship after relationship model update' do
|
67
68
|
like = user.like! movie
|
68
69
|
|
69
|
-
like.neo_relationship.rate.
|
70
|
+
expect(like.neo_relationship.rate).to be_nil
|
70
71
|
|
71
72
|
like.rate = 10
|
72
73
|
like.save!
|
73
74
|
|
74
|
-
like.neo_relationship.rate.
|
75
|
+
expect(like.neo_relationship.rate).to eq(10)
|
75
76
|
end
|
76
77
|
|
77
|
-
context
|
78
|
-
let(:user) { User.create(name:
|
78
|
+
context 'polymorphic relationship' do
|
79
|
+
let(:user) { User.create(name: 'Elad Ossadon', slug: 'elado') }
|
79
80
|
|
80
|
-
it
|
81
|
+
it 'should create relationships with polymorphic items' do
|
82
|
+
pending
|
81
83
|
followed = [
|
82
|
-
User.create(name:
|
83
|
-
Movie.create(name:
|
84
|
-
Movie.create(name:
|
84
|
+
User.create(name: 'Some One', slug: 'someone'),
|
85
|
+
Movie.create(name: 'The Prestige'),
|
86
|
+
Movie.create(name: 'The Dark Knight')
|
85
87
|
]
|
86
88
|
|
87
89
|
expect {
|
88
90
|
followed.each do |item|
|
89
91
|
user.user_follows.create!(item: item)
|
90
92
|
end
|
91
|
-
}.to change{ user.neo_node.outgoing(:follows).length }.to(followed.length)
|
93
|
+
}.to change { user.neo_node.outgoing(:follows).length }.to(followed.length)
|
92
94
|
|
93
95
|
expect {
|
94
96
|
user.user_follows = user.user_follows[0...1]
|
95
|
-
}.to change{ user.neo_node.outgoing(:follows).length }.to(1)
|
97
|
+
}.to change { user.neo_node.outgoing(:follows).length }.to(1)
|
96
98
|
|
97
99
|
expect {
|
98
100
|
user.user_follows = []
|
99
|
-
}.to change{ user.neo_node.outgoing(:follows).length }.to(0)
|
101
|
+
}.to change { user.neo_node.outgoing(:follows).length }.to(0)
|
100
102
|
end
|
101
103
|
end
|
102
104
|
end
|
data/spec/neoid/search_spec.rb
CHANGED
@@ -1,30 +1,30 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Neoid::ModelAdditions do
|
4
|
-
context
|
4
|
+
context 'search' do
|
5
5
|
let(:index_name) { "articles_search_index_#{Time.now.to_f.to_s.gsub('.', '')}" }
|
6
|
-
|
7
|
-
it
|
8
|
-
Neoid.db.create_node_index(index_name,
|
9
|
-
|
10
|
-
n = Neography::Node.create(name:
|
11
|
-
Neoid.db.add_node_to_index(index_name,
|
12
|
-
Neoid.db.add_node_to_index(index_name,
|
13
|
-
|
6
|
+
|
7
|
+
it 'should index and find node in fulltext' do
|
8
|
+
Neoid.db.create_node_index(index_name, 'fulltext', 'lucene')
|
9
|
+
|
10
|
+
n = Neography::Node.create(name: 'test hello world', year: 2012)
|
11
|
+
Neoid.db.add_node_to_index(index_name, 'name', n.name, n)
|
12
|
+
Neoid.db.add_node_to_index(index_name, 'year', n.year, n)
|
13
|
+
|
14
14
|
[
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
'name:test',
|
16
|
+
'year:2012',
|
17
|
+
'name:test AND year:2012'
|
18
18
|
].each { |q|
|
19
19
|
results = Neoid.db.find_node_index(index_name, q)
|
20
|
-
results.length.
|
21
|
-
Neoid.db.send(:get_id, results).
|
20
|
+
expect(results.length).to eq(1)
|
21
|
+
expect(Neoid.db.send(:get_id, results)).to eq(n.neo_id)
|
22
22
|
}
|
23
23
|
end
|
24
|
-
|
25
|
-
it
|
24
|
+
|
25
|
+
it 'should index item on save' do
|
26
26
|
r = rand(1000000)
|
27
|
-
article = Article.create!(title: "Hello world #{r}", body:
|
27
|
+
article = Article.create!(title: "Hello world #{r}", body: 'Lorem ipsum dolor sit amet', year: r)
|
28
28
|
|
29
29
|
[
|
30
30
|
"title:#{r}",
|
@@ -33,58 +33,83 @@ describe Neoid::ModelAdditions do
|
|
33
33
|
].each do |q|
|
34
34
|
results = Neoid.db.find_node_index(Neoid::DEFAULT_FULLTEXT_SEARCH_INDEX_NAME, q)
|
35
35
|
|
36
|
-
results.
|
37
|
-
results.length.
|
38
|
-
Neoid.db.send(:get_id, results).
|
36
|
+
expect(results).to_not be_nil
|
37
|
+
expect(results.length).to eq(1)
|
38
|
+
expect(Neoid.db.send(:get_id, results)).to eq(article.neo_node.neo_id)
|
39
39
|
end
|
40
40
|
end
|
41
|
-
|
42
|
-
context
|
43
|
-
it
|
44
|
-
Article.neo_search(
|
41
|
+
|
42
|
+
context 'search session' do
|
43
|
+
it 'should return a search session' do
|
44
|
+
expect(Article.neo_search('hello')).to be_a(Neoid::SearchSession)
|
45
45
|
end
|
46
|
-
|
47
|
-
it
|
48
|
-
article = Article.create!(title:
|
49
|
-
|
50
|
-
Article.neo_search(
|
46
|
+
|
47
|
+
it 'should find hits' do
|
48
|
+
article = Article.create!(title: 'Hello world', body: 'Lorem ipsum dolor sit amet', year: 2012)
|
49
|
+
|
50
|
+
expect(Article.neo_search('hello').hits).to eq([article.neo_node])
|
51
51
|
end
|
52
|
-
|
53
|
-
it "should find results with a search string" do
|
54
|
-
article = Article.create!(title: "Hello world", body: "Lorem ipsum dolor sit amet", year: 2012)
|
55
52
|
|
56
|
-
|
53
|
+
it 'should find results with a search string' do
|
54
|
+
article = Article.create!(title: 'Hello world', body: 'Lorem ipsum dolor sit amet', year: 2012)
|
55
|
+
|
56
|
+
expect(Article.neo_search('hello').results).to eq([article])
|
57
57
|
end
|
58
|
-
|
59
|
-
it
|
58
|
+
|
59
|
+
it 'should find results with a hash' do
|
60
60
|
articles = [
|
61
|
-
Article.create!(title:
|
62
|
-
Article.create!(title:
|
61
|
+
Article.create!(title: 'How to draw manga', body: 'Lorem ipsum dolor sit amet', year: 2012),
|
62
|
+
Article.create!(title: 'Manga x', body: 'Lorem ipsum dolor sit amet', year: 2013)
|
63
63
|
]
|
64
64
|
|
65
65
|
|
66
|
-
Article.neo_search(year: 2012).results.
|
66
|
+
expect(Article.neo_search(year: 2012).results).to eq([articles[0]])
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
-
context
|
70
|
+
context 'in multiple types' do
|
71
71
|
before :each do
|
72
72
|
@articles = [
|
73
|
-
Article.create!(title:
|
74
|
-
Article.create!(title:
|
73
|
+
Article.create!(title: 'How to draw manga', body: 'Lorem ipsum dolor sit amet', year: 2012),
|
74
|
+
Article.create!(title: 'Manga x', body: 'Lorem ipsum dolor sit amet', year: 2012)
|
75
75
|
]
|
76
76
|
|
77
77
|
@movies = [
|
78
|
-
Movie.create!(name:
|
78
|
+
Movie.create!(name: 'Anime is not Manga', slug: 'anime')
|
79
79
|
]
|
80
80
|
end
|
81
81
|
|
82
|
-
it
|
83
|
-
Neoid.search([Article, Movie],
|
82
|
+
it 'should search in multiple types' do
|
83
|
+
expect(Neoid.search([Article, Movie], 'manga').results).to match_array(@articles + @movies)
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should search in single type when specified' do
|
87
|
+
expect(Neoid.search([Article], 'manga').results).to match_array(@articles)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context 'matching types' do
|
92
|
+
before :each do
|
93
|
+
Article.create!(title: 'Comics: How to draw manga', body: 'Lorem ipsum dolor sit amet', year: 2012)
|
94
|
+
Article.create!(title: 'Manga x', body: 'Lorem ipsum dolor sit amet', year: 2012)
|
95
|
+
Article.create!(title: 'hidden secrets of comics masters', body: 'Lorem ipsum dolor sit amet', year: 2012)
|
96
|
+
Article.create!(title: 'hidden secrets of manga comics artists', body: 'Lorem ipsum dolor sit amet', year: 2012)
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'will match by keyword' do
|
100
|
+
expect(Neoid.search([Article], 'manga comics').results.size).to eq(1)
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'will match with AND' do
|
104
|
+
expect(Neoid.search([Article], 'manga comics', match_type: 'AND').results.size).to eq(1)
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'will match with OR' do
|
108
|
+
expect(Neoid.search([Article], 'manga comics', match_type: 'OR').results.size).to eq(4)
|
84
109
|
end
|
85
110
|
|
86
|
-
it
|
87
|
-
Neoid.search([Article],
|
111
|
+
it 'will fail with wrong match_type' do
|
112
|
+
expect { Neoid.search([Article], 'manga comics', match_type: 'MAYBE') }.to raise_error('Invalid match_type option. Valid values are AND,OR')
|
88
113
|
end
|
89
114
|
end
|
90
115
|
end
|
data/spec/neoid_spec.rb
CHANGED
@@ -1,11 +1,18 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Neoid do
|
4
|
-
context
|
5
|
-
|
4
|
+
context 'subrefs' do
|
5
|
+
before(:each) do
|
6
|
+
# first we have to enable subrefs
|
7
|
+
Neoid.config.enable_subrefs = true
|
8
|
+
# now that its enabled, we re-initialize the module
|
9
|
+
Neoid.initialize_all
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should create all subrefs on initialization' do
|
6
13
|
Neoid.node_models.each do |klass|
|
7
|
-
klass.instance_variable_get(:@neo_subref_node).
|
14
|
+
expect(klass.instance_variable_get(:@neo_subref_node)).to_not be_nil
|
8
15
|
end
|
9
16
|
end
|
10
17
|
end
|
11
|
-
end
|
18
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -2,10 +2,23 @@ require 'neoid'
|
|
2
2
|
require 'active_record'
|
3
3
|
require 'neography'
|
4
4
|
require 'rest-client'
|
5
|
+
require 'codeclimate-test-reporter'
|
6
|
+
require 'factory_girl'
|
7
|
+
require 'rspec/its'
|
5
8
|
|
6
|
-
|
9
|
+
CodeClimate::TestReporter.start if ENV['CODECLIMATE_REPO_TOKEN']
|
7
10
|
|
8
|
-
|
11
|
+
require 'simplecov'
|
12
|
+
|
13
|
+
require "factories.rb"
|
14
|
+
|
15
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
16
|
+
SimpleCov::Formatter::HTMLFormatter,
|
17
|
+
]
|
18
|
+
|
19
|
+
SimpleCov.start
|
20
|
+
|
21
|
+
uri = URI.parse('http://localhost:7474')
|
9
22
|
$neo = Neography::Rest.new(uri.to_s)
|
10
23
|
|
11
24
|
Neography.configure do |c|
|
@@ -21,9 +34,13 @@ end
|
|
21
34
|
|
22
35
|
Neoid.db = $neo
|
23
36
|
|
37
|
+
Neoid.configure do |config|
|
38
|
+
config.enable_subrefs = false
|
39
|
+
end
|
40
|
+
|
24
41
|
logger, ActiveRecord::Base.logger = ActiveRecord::Base.logger, Logger.new('/dev/null')
|
25
42
|
ActiveRecord::Base.configurations = YAML::load(IO.read(File.join(File.dirname(__FILE__), 'support/database.yml')))
|
26
|
-
ActiveRecord::Base.establish_connection(
|
43
|
+
ActiveRecord::Base.establish_connection(:sqlite3)
|
27
44
|
|
28
45
|
require 'support/schema'
|
29
46
|
require 'support/models'
|
@@ -31,11 +48,13 @@ require 'support/models'
|
|
31
48
|
ActiveRecord::Base.logger = logger
|
32
49
|
|
33
50
|
RSpec.configure do |config|
|
51
|
+
config.include FactoryGirl::Syntax::Methods
|
52
|
+
|
34
53
|
config.mock_with :rspec
|
35
54
|
|
36
55
|
config.before(:all) do
|
37
56
|
end
|
38
|
-
|
57
|
+
|
39
58
|
config.before(:each) do
|
40
59
|
Neoid.node_models.each(&:destroy_all)
|
41
60
|
Neoid.clean_db(:yes_i_am_sure)
|
data/spec/support/database.yml
CHANGED
data/spec/support/models.rb
CHANGED
@@ -1,26 +1,26 @@
|
|
1
1
|
class User < ActiveRecord::Base
|
2
2
|
include ActiveModel::Validations::Callbacks
|
3
|
-
|
3
|
+
|
4
4
|
has_many :likes
|
5
5
|
has_many :movies, through: :likes
|
6
6
|
|
7
7
|
has_many :user_follows
|
8
|
-
|
8
|
+
|
9
9
|
def likes?(movie)
|
10
10
|
likes.where(movie_id: movie.id).exists?
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
def like!(movie)
|
14
14
|
movies << movie unless likes?(movie)
|
15
15
|
likes.where(movie_id: movie.id).first
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
def unlike!(movie)
|
19
|
-
likes.where(movie_id: movie.id, user_id:
|
19
|
+
likes.where(movie_id: movie.id, user_id: id).destroy_all
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
include Neoid::Node
|
23
|
-
|
23
|
+
|
24
24
|
neoidable do |c|
|
25
25
|
c.field :name
|
26
26
|
c.field :slug
|
@@ -29,12 +29,12 @@ end
|
|
29
29
|
|
30
30
|
class Movie < ActiveRecord::Base
|
31
31
|
include ActiveModel::Validations::Callbacks
|
32
|
-
|
32
|
+
|
33
33
|
has_many :likes
|
34
34
|
has_many :users, through: :likes
|
35
|
-
|
35
|
+
|
36
36
|
include Neoid::Node
|
37
|
-
|
37
|
+
|
38
38
|
neoidable do |c|
|
39
39
|
c.field :name
|
40
40
|
c.field :slug
|
@@ -55,9 +55,9 @@ class UserFollow < ActiveRecord::Base
|
|
55
55
|
|
56
56
|
belongs_to :user
|
57
57
|
belongs_to :item, polymorphic: true
|
58
|
-
|
58
|
+
|
59
59
|
include Neoid::Relationship
|
60
|
-
|
60
|
+
|
61
61
|
neoidable do |c|
|
62
62
|
c.relationship start_node: :user, end_node: :item, type: :follows
|
63
63
|
end
|
@@ -65,12 +65,12 @@ end
|
|
65
65
|
|
66
66
|
class Like < ActiveRecord::Base
|
67
67
|
include ActiveModel::Validations::Callbacks
|
68
|
-
|
68
|
+
|
69
69
|
belongs_to :user
|
70
70
|
belongs_to :movie
|
71
|
-
|
71
|
+
|
72
72
|
include Neoid::Relationship
|
73
|
-
|
73
|
+
|
74
74
|
neoidable do |c|
|
75
75
|
c.relationship start_node: :user, end_node: :movie, type: :likes
|
76
76
|
c.field :rate
|
@@ -84,7 +84,7 @@ class Article < ActiveRecord::Base
|
|
84
84
|
c.field :title
|
85
85
|
c.field :year
|
86
86
|
c.field :title_length do
|
87
|
-
|
87
|
+
title ? title.length : 0
|
88
88
|
end
|
89
89
|
|
90
90
|
c.search do |s|
|