neoid 0.0.2 → 0.0.5.alpha

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,90 +1,18 @@
1
- require 'spec_helper'
2
-
3
- class User < SuperModel::Base
4
- include ActiveModel::Validations::Callbacks
5
-
6
- has_many :likes
7
- has_many :movies, through: :likes
8
-
9
-
10
- # _test_movies is here because SuperModel doesn't handle has_many queries
11
- # it simulates the database. see comments in each method to see a regular AR implementation
12
- def _test_movies
13
- @_test_movies ||= []
14
- end
15
-
16
- def likes?(movie)
17
- # likes.where(movie_id: movie.id).exists?
18
- _test_movies.any? { |it| it.movie_id == movie.id }
19
- end
20
-
21
- def like!(movie)
22
- # movies << movie unless likes?(movie)
23
- _test_movies << Like.create(user_id: self.id, movie_id: movie.id) unless likes?(movie)
24
- end
25
-
26
- def unlike!(movie)
27
- # likes.where(movie_id: movie.id, user_id: self.id).destroy_all
28
- _test_movies.delete_if { |it| it.destroy if it.movie_id == movie.id }
29
- end
30
-
31
- include Neoid::Node
32
-
33
- def to_neo
34
- neo_properties_to_hash(%w( name slug ))
35
- end
36
- end
37
-
38
- class Movie < SuperModel::Base
39
- include ActiveModel::Validations::Callbacks
40
-
41
- has_many :likes
42
- has_many :users, through: :likes
43
-
44
- include Neoid::Node
45
-
46
- def to_neo
47
- neo_properties_to_hash(%w( name slug year ))
48
- end
49
- end
50
-
51
- class Like < SuperModel::Base
52
- include ActiveModel::Validations::Callbacks
53
-
54
- belongs_to :user
55
- belongs_to :movie
56
-
57
- include Neoid::Relationship
58
-
59
- neoidable start_node: :user, end_node: :movie, type: :likes
60
-
61
- def to_neo
62
- neo_properties_to_hash(%w( rate ))
63
- end
64
- end
65
-
66
1
  require 'spec_helper'
67
2
  require 'fileutils'
68
3
 
69
4
  describe Neoid::ModelAdditions do
70
- before(:each) do
71
- [ User, Movie ].each { |klass|
72
- klass.instance_variable_set(:@_neo_subref_node, nil)
73
- }
74
- Neoid.ref_node = nil
75
- end
76
-
77
5
  context "nodes" do
78
6
  context "create graph nodes" do
79
7
  it "should call neo_create on a neo_node for user" do
80
8
  User.any_instance.should_receive(:neo_create)
81
9
 
82
- User.create(name: "Elad Ossadon")
10
+ User.create!(name: "Elad Ossadon")
83
11
  end
84
12
 
85
13
  it "should create a neo_node for user" do
86
- user = User.create(name: "Elad Ossadon", slug: "elado")
87
-
14
+ user = User.create!(name: "Elad Ossadon", slug: "elado")
15
+
88
16
  user.neo_node.should_not be_nil
89
17
 
90
18
  user.neo_node.ar_id.should == user.id
@@ -93,7 +21,7 @@ describe Neoid::ModelAdditions do
93
21
  end
94
22
 
95
23
  it "should create a neo_node for movie" do
96
- movie = Movie.create(name: "Memento", slug: "memento-1999", year: 1999)
24
+ movie = Movie.create!(name: "Memento", slug: "memento-1999", year: 1999)
97
25
 
98
26
  movie.neo_node.should_not be_nil
99
27
 
@@ -105,7 +33,7 @@ describe Neoid::ModelAdditions do
105
33
 
106
34
  context "find by id" do
107
35
  it "should find a neo_node for user" do
108
- user = User.create(name: "Elad Ossadon", slug: "elado")
36
+ user = User.create!(name: "Elad Ossadon", slug: "elado")
109
37
 
110
38
  user.neo_node.should_not be_nil
111
39
  user.neo_find_by_id.should_not be_nil
@@ -132,7 +60,7 @@ describe Neoid::ModelAdditions do
132
60
 
133
61
  it "should delete a relationship on deleting a record" do
134
62
  user.like! movie
135
- like = user.likes.first
63
+ like = user.likes.last
136
64
 
137
65
  relationship_neo_id = like.neo_relationship.neo_id
138
66
 
@@ -140,7 +68,61 @@ describe Neoid::ModelAdditions do
140
68
 
141
69
  user.unlike! movie
142
70
 
143
- Neography::Relationship.load(relationship_neo_id).should be_nil
71
+ expect { Neography::Relationship.load(relationship_neo_id) }.to raise_error(Neography::RelationshipNotFoundException)
72
+ end
73
+
74
+ it "should update neo4j on manual set of a collection" do
75
+ movies = [
76
+ Movie.create(name: "Memento"),
77
+ Movie.create(name: "The Prestige"),
78
+ Movie.create(name: "The Dark Knight"),
79
+ Movie.create(name: "Spiderman")
80
+ ]
81
+
82
+ user.neo_node.outgoing(:likes).length.should == 0
83
+
84
+ expect {
85
+ user.movies = movies
86
+ }.to change{ user.neo_node.outgoing(:likes).length }.to(movies.length)
87
+
88
+ expect { expect {
89
+ user.movies -= movies[0..1]
90
+ }.to change{ user.movies.count }.by(-2)
91
+ }.to change{ user.neo_node.outgoing(:likes).length }.by(-2)
92
+
93
+ expect {
94
+ user.movies = []
95
+ }.to change{ user.neo_node.outgoing(:likes).length }.to(0)
96
+
97
+ expect {
98
+ user.movie_ids = movies[0...2].collect(&:id)
99
+ }.to change{ user.neo_node.outgoing(:likes).length }.to(2)
100
+ end
101
+ end
102
+
103
+ context "polymorphic relationship" do
104
+ let(:user) { User.create(name: "Elad Ossadon", slug: "elado") }
105
+
106
+ it "description" do
107
+ followed = [
108
+ User.create(name: "Some One", slug: "someone"),
109
+ Movie.create(name: "The Prestige"),
110
+ Movie.create(name: "The Dark Knight")
111
+ ]
112
+
113
+ expect {
114
+ followed.each do |item|
115
+ user.user_follows.create(item: item)
116
+ end
117
+ }.to change{ user.neo_node.outgoing(:follows).length }.to(followed.length)
118
+
119
+ expect {
120
+ user.user_follows = user.user_follows[0...1]
121
+ }.to change{ user.neo_node.outgoing(:follows).length }.to(1)
122
+
123
+ expect {
124
+ user.user_follows = []
125
+ }.to change{ user.neo_node.outgoing(:follows).length }.to(0)
144
126
  end
145
127
  end
146
128
  end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+ require 'fileutils'
3
+
4
+
5
+ describe Neoid::ModelConfig do
6
+ context "config on a model" do
7
+ it "should store search fields" do
8
+ Article.neoid_config.search_options.should_not be_nil
9
+ Article.neoid_config.search_options.index_fields.keys.should =~ [ :title, :body, :year ]
10
+ end
11
+
12
+ it "should store stored fields" do
13
+ Article.neoid_config.stored_fields.should_not be_nil
14
+ Article.neoid_config.stored_fields.keys.should =~ [ :title, :year, :title_length ]
15
+ Article.neoid_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,92 @@
1
+ require 'spec_helper'
2
+ require 'fileutils'
3
+
4
+ describe Neoid::ModelAdditions do
5
+ context "search" do
6
+ let(:index_name) { "articles_search_index_#{Time.now.to_f.to_s.gsub('.', '')}" }
7
+
8
+ it "should index and find node in fulltext" do
9
+ Neoid.db.create_node_index(index_name, "fulltext", "lucene")
10
+
11
+ n = Neography::Node.create(name: "test hello world", year: 2012)
12
+ Neoid.db.add_node_to_index(index_name, "name", n.name, n)
13
+ Neoid.db.add_node_to_index(index_name, "year", n.year, n)
14
+
15
+ [
16
+ "name:test",
17
+ "year:2012",
18
+ "name:test AND year:2012"
19
+ ].each { |q|
20
+ results = Neoid.db.find_node_index(index_name, q)
21
+ results.length.should == 1
22
+ Neoid.db.send(:get_id, results).should == n.neo_id
23
+ }
24
+ end
25
+
26
+ it "should index item on save" do
27
+ r = rand(1000000)
28
+ article = Article.create!(title: "Hello world #{r}", body: "Lorem ipsum dolor sit amet", year: r)
29
+
30
+ [
31
+ "title:#{r}",
32
+ "year:#{r}",
33
+ "title:#{r} AND year:#{r}"
34
+ ].each do |q|
35
+ results = Neoid.db.find_node_index(Neoid::DEFAULT_FULLTEXT_SEARCH_INDEX_NAME, q)
36
+
37
+ results.should_not be_nil
38
+ results.length.should == 1
39
+ Neoid.db.send(:get_id, results).should == article.neo_node.neo_id
40
+ end
41
+ end
42
+
43
+ context "search session" do
44
+ it "should return a search session" do
45
+ Article.neo_search("hello").should be_a(Neoid::SearchSession)
46
+ end
47
+
48
+ it "should find hits" do
49
+ article = Article.create!(title: "Hello world", body: "Lorem ipsum dolor sit amet", year: 2012)
50
+
51
+ Article.neo_search("hello").hits.should == [ article.neo_node ]
52
+ end
53
+
54
+ it "should find results with a search string" do
55
+ article = Article.create!(title: "Hello world", body: "Lorem ipsum dolor sit amet", year: 2012)
56
+
57
+ Article.neo_search("hello").results.should == [ article ]
58
+ end
59
+
60
+ it "should find results with a hash" do
61
+ articles = [
62
+ Article.create!(title: "How to draw manga", body: "Lorem ipsum dolor sit amet", year: 2012),
63
+ Article.create!(title: "Manga x", body: "Lorem ipsum dolor sit amet", year: 2013)
64
+ ]
65
+
66
+
67
+ Article.neo_search(year: 2012).results.should == [ articles[0] ]
68
+ end
69
+ end
70
+
71
+ context "search in multiple types" do
72
+ before :each do
73
+ @articles = [
74
+ Article.create!(title: "How to draw manga", body: "Lorem ipsum dolor sit amet", year: 2012),
75
+ Article.create!(title: "Manga x", body: "Lorem ipsum dolor sit amet", year: 2012)
76
+ ]
77
+
78
+ @movies = [
79
+ Movie.create!(name: "Anime is not Manga", slug: "anime")
80
+ ]
81
+ end
82
+
83
+ it "should search in multiple types" do
84
+ Neoid.search([Article, Movie], "manga").results.should =~ @articles + @movies
85
+ end
86
+
87
+ it "should search in single type when specified" do
88
+ Neoid.search([Article], "manga").results.should =~ @articles
89
+ end
90
+ end
91
+ end
92
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,12 +1,12 @@
1
1
  require 'neoid'
2
- require 'supermodel'
2
+ require 'active_record'
3
3
  require 'neography'
4
4
  require 'rest-client'
5
5
 
6
- uri = URI.parse(ENV["NEO4J_URL"] || "http://localhost:7574")
6
+ uri = URI.parse(ENV["NEO4J_URL"] ? ENV["NEO4J_URL"] : ENV['TRAVIS'] ? "http://localhost:7474" : "http://localhost:7574")
7
7
  $neo = Neography::Rest.new(uri.to_s)
8
8
 
9
- Neography::Config.tap do |c|
9
+ Neography.configure do |c|
10
10
  c.server = uri.host
11
11
  c.port = uri.port
12
12
 
@@ -19,10 +19,26 @@ end
19
19
 
20
20
  Neoid.db = $neo
21
21
 
22
+ ActiveRecord::Base.configurations = YAML::load(IO.read(File.join(File.dirname(__FILE__), 'support/database.yml')))
23
+ ActiveRecord::Base.establish_connection('sqlite3')
24
+
22
25
  RSpec.configure do |config|
23
26
  config.mock_with :rspec
24
27
 
25
28
  config.before(:all) do
26
- RestClient.delete "#{uri}/cleandb/secret-key"
29
+ end
30
+
31
+ config.before(:each) do
32
+ Neoid.reset_cached_variables
33
+ end
34
+
35
+ config.before(:each) do
36
+ Neoid.clean_db(:yes_i_am_sure)
37
+ Neoid.models.each(&:destroy_all)
27
38
  end
28
39
  end
40
+
41
+ require 'support/schema'
42
+ require 'support/models'
43
+
44
+ Neoid.initialize_all
@@ -0,0 +1,6 @@
1
+ sqlite3:
2
+ adapter: sqlite3
3
+ database: ":memory:"
4
+ encoding: utf8
5
+ charset: utf8
6
+ timeout: 5000
@@ -0,0 +1,97 @@
1
+ class User < ActiveRecord::Base
2
+ include ActiveModel::Validations::Callbacks
3
+
4
+ has_many :likes
5
+ has_many :movies, through: :likes
6
+
7
+ has_many :user_follows
8
+
9
+ def likes?(movie)
10
+ likes.where(movie_id: movie.id).exists?
11
+ end
12
+
13
+ def like!(movie)
14
+ movies << movie unless likes?(movie)
15
+ end
16
+
17
+ def unlike!(movie)
18
+ likes.where(movie_id: movie.id, user_id: self.id).destroy_all
19
+ end
20
+
21
+ include Neoid::Node
22
+
23
+ neoidable do |c|
24
+ c.field :name
25
+ c.field :slug
26
+ end
27
+ end
28
+
29
+ class Movie < ActiveRecord::Base
30
+ include ActiveModel::Validations::Callbacks
31
+
32
+ has_many :likes
33
+ has_many :users, through: :likes
34
+
35
+ include Neoid::Node
36
+
37
+ neoidable do |c|
38
+ c.field :name
39
+ c.field :slug
40
+ c.field :year
41
+
42
+ c.search do |s|
43
+ s.fulltext :name
44
+
45
+ s.index :name
46
+ s.index :slug
47
+ s.index :year
48
+ end
49
+ end
50
+ end
51
+
52
+ class UserFollow < ActiveRecord::Base
53
+ include ActiveModel::Validations::Callbacks
54
+
55
+ belongs_to :user, dependent: :destroy
56
+ belongs_to :item, polymorphic: true
57
+
58
+ include Neoid::Relationship
59
+
60
+ neoidable do |c|
61
+ c.relationship start_node: :user, end_node: :item, type: :follows
62
+ end
63
+ end
64
+
65
+ class Like < ActiveRecord::Base
66
+ include ActiveModel::Validations::Callbacks
67
+
68
+ belongs_to :user, dependent: :destroy
69
+ belongs_to :movie, dependent: :destroy
70
+
71
+ include Neoid::Relationship
72
+
73
+ neoidable do |c|
74
+ c.relationship start_node: :user, end_node: :movie, type: :likes
75
+ c.field :rate
76
+ end
77
+ end
78
+
79
+ class Article < ActiveRecord::Base
80
+ include ActiveModel::Validations::Callbacks
81
+ include Neoid::Node
82
+ neoidable do |c|
83
+ c.field :title
84
+ c.field :year
85
+ c.field :title_length do
86
+ self.title ? self.title.length : 0
87
+ end
88
+
89
+ c.search do |s|
90
+ s.fulltext :title
91
+
92
+ s.index :title
93
+ s.index :body
94
+ s.index :year
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,40 @@
1
+ ActiveRecord::Schema.define :version => 0 do
2
+ create_table :users do |t|
3
+ t.string :name
4
+ t.string :slug
5
+
6
+ t.timestamps
7
+ end
8
+
9
+ create_table :movies do |t|
10
+ t.string :name
11
+ t.string :slug
12
+ t.integer :year
13
+
14
+ t.timestamps
15
+ end
16
+
17
+ create_table :likes do |t|
18
+ t.integer :user_id
19
+ t.integer :movie_id
20
+ t.integer :rate
21
+
22
+ t.timestamps
23
+ end
24
+
25
+
26
+ create_table :articles do |t|
27
+ t.string :title
28
+ t.string :body
29
+ t.integer :year
30
+
31
+ t.timestamps
32
+ end
33
+
34
+ create_table :user_follows do |t|
35
+ t.belongs_to :user
36
+ t.belongs_to :item, polymorphic: true
37
+
38
+ t.timestamps
39
+ end
40
+ end
metadata CHANGED
@@ -1,19 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: neoid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
5
- prerelease:
4
+ version: 0.0.5.alpha
5
+ prerelease: 6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Elad Ossadon
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-21 00:00:00.000000000 Z
12
+ date: 2012-12-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
16
- requirement: &70163085349120 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70163085349120
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: rspec
27
- requirement: &70163085342100 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,10 +37,31 @@ dependencies:
32
37
  version: '0'
33
38
  type: :development
34
39
  prerelease: false
35
- version_requirements: *70163085342100
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: rest-client
38
- requirement: &70163085341480 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: activerecord
64
+ requirement: !ruby/object:Gem::Requirement
39
65
  none: false
40
66
  requirements:
41
67
  - - ! '>='
@@ -43,10 +69,15 @@ dependencies:
43
69
  version: '0'
44
70
  type: :development
45
71
  prerelease: false
46
- version_requirements: *70163085341480
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
47
78
  - !ruby/object:Gem::Dependency
48
- name: supermodel
49
- requirement: &70163085341000 !ruby/object:Gem::Requirement
79
+ name: sqlite3
80
+ requirement: !ruby/object:Gem::Requirement
50
81
  none: false
51
82
  requirements:
52
83
  - - ! '>='
@@ -54,10 +85,15 @@ dependencies:
54
85
  version: '0'
55
86
  type: :development
56
87
  prerelease: false
57
- version_requirements: *70163085341000
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
58
94
  - !ruby/object:Gem::Dependency
59
95
  name: neography
60
- requirement: &70163085340500 !ruby/object:Gem::Requirement
96
+ requirement: !ruby/object:Gem::Requirement
61
97
  none: false
62
98
  requirements:
63
99
  - - ! '>='
@@ -65,7 +101,12 @@ dependencies:
65
101
  version: '0'
66
102
  type: :runtime
67
103
  prerelease: false
68
- version_requirements: *70163085340500
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
69
110
  description: Extend Ruby on Rails ActiveRecord with Neo4j nodes. Keep RDBMS and utilize
70
111
  the power of Neo4j queries
71
112
  email:
@@ -76,21 +117,32 @@ extra_rdoc_files: []
76
117
  files:
77
118
  - .gitignore
78
119
  - .rspec
120
+ - .travis.yml
79
121
  - CHANGELOG.md
80
122
  - Gemfile
81
123
  - LICENSE
82
124
  - README.md
83
125
  - Rakefile
126
+ - TODO.md
84
127
  - lib/neoid.rb
128
+ - lib/neoid/database_cleaner.rb
129
+ - lib/neoid/middleware.rb
85
130
  - lib/neoid/model_additions.rb
86
131
  - lib/neoid/model_config.rb
87
132
  - lib/neoid/node.rb
133
+ - lib/neoid/railtie.rb
88
134
  - lib/neoid/relationship.rb
135
+ - lib/neoid/search_session.rb
89
136
  - lib/neoid/version.rb
90
137
  - neoid.gemspec
91
138
  - spec/neoid/model_additions_spec.rb
139
+ - spec/neoid/model_config_spec.rb
140
+ - spec/neoid/search_spec.rb
92
141
  - spec/neoid_spec.rb
93
142
  - spec/spec_helper.rb
143
+ - spec/support/database.yml
144
+ - spec/support/models.rb
145
+ - spec/support/schema.rb
94
146
  homepage: ''
95
147
  licenses: []
96
148
  post_install_message:
@@ -103,25 +155,25 @@ required_ruby_version: !ruby/object:Gem::Requirement
103
155
  - - ! '>='
104
156
  - !ruby/object:Gem::Version
105
157
  version: '0'
106
- segments:
107
- - 0
108
- hash: -1739317772889618819
109
158
  required_rubygems_version: !ruby/object:Gem::Requirement
110
159
  none: false
111
160
  requirements:
112
- - - ! '>='
161
+ - - ! '>'
113
162
  - !ruby/object:Gem::Version
114
- version: '0'
115
- segments:
116
- - 0
117
- hash: -1739317772889618819
163
+ version: 1.3.1
118
164
  requirements: []
119
165
  rubyforge_project: neoid
120
- rubygems_version: 1.8.10
166
+ rubygems_version: 1.8.24
121
167
  signing_key:
122
168
  specification_version: 3
123
169
  summary: Neo4j for ActiveRecord
124
170
  test_files:
125
171
  - spec/neoid/model_additions_spec.rb
172
+ - spec/neoid/model_config_spec.rb
173
+ - spec/neoid/search_spec.rb
126
174
  - spec/neoid_spec.rb
127
175
  - spec/spec_helper.rb
176
+ - spec/support/database.yml
177
+ - spec/support/models.rb
178
+ - spec/support/schema.rb
179
+ has_rdoc: