neoid 0.0.2 → 0.0.5.alpha

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.
@@ -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: