neoid 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  module Neoid
2
2
  class NeoDatabaseCleaner
3
- def self.clean_db(start_node = Neoid.db.get_root)
3
+ def self.clean_db()
4
4
  Neoid.db.execute_script <<-GREMLIN
5
5
  g.V.toList().each { if (it.id != 0) g.removeVertex(it) }
6
6
  g.indices.each { g.dropIndex(it.indexName); }
@@ -1,4 +1,4 @@
1
- module Ndoid
1
+ module Neoid
2
2
  class Middleware
3
3
  def initialize(app)
4
4
  @app = app
@@ -2,11 +2,11 @@ module Neoid
2
2
  module ModelAdditions
3
3
  module ClassMethods
4
4
  attr_reader :neoid_config
5
-
5
+
6
6
  def neoid_config
7
7
  @neoid_config ||= Neoid::ModelConfig.new(self)
8
8
  end
9
-
9
+
10
10
  def neoidable(options = {})
11
11
  # defaults
12
12
  neoid_config.auto_index = true
@@ -15,17 +15,17 @@ module Neoid
15
15
  yield(neoid_config) if block_given?
16
16
 
17
17
  options.each do |key, value|
18
- raise "Neoid #{self.name} model options: No such option #{key}" unless neoid_config.respond_to?("#{key}=")
18
+ raise "Neoid #{name} model options: No such option #{key}" unless neoid_config.respond_to?("#{key}=")
19
19
  neoid_config.send("#{key}=", value)
20
20
  end
21
21
  end
22
22
 
23
23
  def neo_model_index_name
24
- raise "Per Model index is not enabled. Nodes/Relationships are auto indexed with node_auto_index/relationship_auto_index" unless Neoid.config.enable_per_model_indexes || neoid_config.enable_model_index
25
- @index_name ||= "#{self.name.tableize}_index"
24
+ raise 'Per Model index is not enabled. Nodes/Relationships are auto indexed with node_auto_index/relationship_auto_index' unless Neoid.config.enable_per_model_indexes || neoid_config.enable_model_index
25
+ @index_name ||= "#{name.tableize}_index"
26
26
  end
27
27
  end
28
-
28
+
29
29
  module InstanceMethods
30
30
  def to_neo
31
31
  if self.class.neoid_config.stored_fields
@@ -33,9 +33,9 @@ module Neoid
33
33
  all[field] = if block
34
34
  instance_eval(&block)
35
35
  else
36
- self.send(field) rescue (raise "No field #{field} for #{self.class.name}")
36
+ send(field) rescue (raise "No field #{field} for #{self.class.name}")
37
37
  end
38
-
38
+
39
39
  all
40
40
  end
41
41
 
@@ -69,7 +69,7 @@ module Neoid
69
69
  begin
70
70
  neo_representation.del
71
71
  rescue Neography::NodeNotFoundException => e
72
- Neoid::logger.info "Neoid#neo_destroy entity not found #{self.class.name} #{self.id}"
72
+ Neoid::logger.info "Neoid#neo_destroy entity not found #{self.class.name} #{id}"
73
73
  end
74
74
 
75
75
  # 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
@@ -89,18 +89,20 @@ module Neoid
89
89
  end
90
90
 
91
91
  def neo_unique_id
92
- "#{self.class.name}:#{self.id}"
92
+ "#{self.class.name}:#{id}"
93
93
  end
94
94
 
95
95
  protected
96
+
96
97
  def neo_properties_to_hash(*attribute_list)
97
98
  attribute_list.flatten.inject({}) { |all, property|
98
- all[property] = self.send(property)
99
+ all[property] = send(property)
99
100
  all
100
101
  }
101
102
  end
102
103
 
103
104
  private
105
+
104
106
  def _neo_representation
105
107
  @_neo_representation ||= neo_find_by_id || neo_save
106
108
  end
@@ -5,34 +5,34 @@ module Neoid
5
5
  attr_reader :relationship_options
6
6
  attr_accessor :enable_model_index
7
7
  attr_accessor :auto_index
8
-
8
+
9
9
  def initialize(klass)
10
10
  @klass = klass
11
11
  end
12
-
12
+
13
13
  def stored_fields
14
14
  @stored_fields ||= {}
15
15
  end
16
-
16
+
17
17
  def field(name, &block)
18
- self.stored_fields[name] = block
18
+ stored_fields[name] = block
19
19
  end
20
-
20
+
21
21
  def relationship(options)
22
22
  @relationship_options = options
23
23
  end
24
-
24
+
25
25
  def search(&block)
26
- raise "search needs a block" unless block_given?
26
+ raise 'search needs a block' unless block_given?
27
27
  @search_options = SearchConfig.new
28
- block.(@search_options)
28
+ block.call(@search_options)
29
29
  end
30
-
30
+
31
31
  def inspect
32
32
  "#<Neoid::ModelConfig @properties=#{properties.inspect} @search_options=#{@search_options.inspect}>"
33
33
  end
34
34
  end
35
-
35
+
36
36
  class SearchConfig
37
37
  def index_fields
38
38
  @index_fields ||= {}
@@ -41,15 +41,15 @@ module Neoid
41
41
  def fulltext_fields
42
42
  @fulltext_fields ||= {}
43
43
  end
44
-
44
+
45
45
  def index(field, options = {}, &block)
46
46
  index_fields[field] = options.merge(block: block)
47
47
  end
48
-
48
+
49
49
  def fulltext(field, options = {}, &block)
50
50
  fulltext_fields[field] = options.merge(block: block)
51
51
  end
52
-
52
+
53
53
  def inspect
54
54
  "#<Neoid::SearchConfig @index_fields=#{index_fields.inspect} @fulltext_fields=#{fulltext_fields.inspect}>"
55
55
  end
@@ -6,15 +6,22 @@ module Neoid
6
6
  node
7
7
  end
8
8
 
9
+ def self.included(receiver)
10
+ receiver.send :include, Neoid::ModelAdditions
11
+ receiver.extend ClassMethods
12
+ receiver.send :include, InstanceMethods
13
+ Neoid.node_models << receiver
14
+ end
15
+
9
16
  module ClassMethods
10
17
  attr_accessor :neo_subref_node
11
18
 
12
19
  def neo_subref_rel_type
13
- @_neo_subref_rel_type ||= "#{self.name.tableize}_subref"
20
+ @_neo_subref_rel_type ||= "#{name.tableize}_subref"
14
21
  end
15
22
 
16
23
  def neo_subref_node_rel_type
17
- @_neo_subref_node_rel_type ||= self.name.tableize
24
+ @_neo_subref_node_rel_type ||= name.tableize
18
25
  end
19
26
 
20
27
  def delete_command
@@ -60,7 +67,7 @@ module Neoid
60
67
 
61
68
  script_vars = {
62
69
  neo_subref_rel_type: neo_subref_rel_type,
63
- name: self.name
70
+ name: name
64
71
  }
65
72
 
66
73
  Neoid.execute_script_or_add_to_batch gremlin_query, script_vars do |value|
@@ -77,18 +84,18 @@ module Neoid
77
84
  Neoid.search(self, term, options)
78
85
  end
79
86
  end
80
-
87
+
81
88
  module InstanceMethods
82
89
  def neo_find_by_id
83
90
  # Neoid::logger.info "Node#neo_find_by_id #{self.class.neo_index_name} #{self.id}"
84
- node = Neoid.db.get_node_auto_index(Neoid::UNIQUE_ID_KEY, self.neo_unique_id)
91
+ node = Neoid.db.get_node_auto_index(Neoid::UNIQUE_ID_KEY, neo_unique_id)
85
92
  node.present? ? Neoid::Node.from_hash(node[0]) : nil
86
93
  end
87
-
94
+
88
95
  def _neo_save
89
96
  return unless Neoid.enabled?
90
97
 
91
- data = self.to_neo.merge(ar_type: self.class.name, ar_id: self.id, Neoid::UNIQUE_ID_KEY => self.neo_unique_id)
98
+ data = to_neo.merge(ar_type: self.class.name, ar_id: id, Neoid::UNIQUE_ID_KEY => neo_unique_id)
92
99
  data.reject! { |k, v| v.nil? }
93
100
 
94
101
  gremlin_query = <<-GREMLIN
@@ -114,10 +121,10 @@ module Neoid
114
121
  node
115
122
  GREMLIN
116
123
 
117
- script_vars = {
124
+ script_vars = {
118
125
  unique_id_key: Neoid::UNIQUE_ID_KEY,
119
126
  node_data: data,
120
- unique_id: self.neo_unique_id,
127
+ unique_id: neo_unique_id,
121
128
  enable_subrefs: Neoid.config.enable_subrefs,
122
129
  enable_model_index: Neoid.config.enable_per_model_indexes && self.class.neoid_config.enable_model_index
123
130
  }
@@ -135,7 +142,7 @@ module Neoid
135
142
  )
136
143
  end
137
144
 
138
- Neoid::logger.info "Node#neo_save #{self.class.name} #{self.id}"
145
+ Neoid::logger.info "Node#neo_save #{self.class.name} #{id}"
139
146
 
140
147
  node = Neoid.execute_script_or_add_to_batch(gremlin_query, script_vars) do |value|
141
148
  @_neo_representation = Neoid::Node.from_hash(value)
@@ -171,14 +178,14 @@ module Neoid
171
178
  if options[:block]
172
179
  options[:block].call
173
180
  else
174
- self.send(field) rescue (raise "No field #{field} for #{self.class.name}")
181
+ send(field) rescue (raise "No field #{field} for #{self.class.name}")
175
182
  end
176
183
  end
177
-
184
+
178
185
  def neo_load(hash)
179
186
  Neoid::Node.from_hash(hash)
180
187
  end
181
-
188
+
182
189
  def neo_node
183
190
  _neo_representation
184
191
  end
@@ -191,7 +198,7 @@ module Neoid
191
198
  rel_model, foreign_key_of_owner, foreign_key_of_record = Neoid::Relationship.meta_data[self.class.name.to_s][record.class.name.to_s]
192
199
  rel_model = rel_model.to_s.constantize
193
200
  @__neo_temp_rels ||= {}
194
- @__neo_temp_rels[record] = rel_model.where(foreign_key_of_owner => self.id, foreign_key_of_record => record.id).first
201
+ @__neo_temp_rels[record] = rel_model.where(foreign_key_of_owner => id, foreign_key_of_record => record.id).first
195
202
  end
196
203
 
197
204
  def neo_after_relationship_through_remove(record)
@@ -199,12 +206,5 @@ module Neoid
199
206
  @__neo_temp_rels.delete(record)
200
207
  end
201
208
  end
202
-
203
- def self.included(receiver)
204
- receiver.send :include, Neoid::ModelAdditions
205
- receiver.extend ClassMethods
206
- receiver.send :include, InstanceMethods
207
- Neoid.node_models << receiver
208
- end
209
209
  end
210
210
  end
@@ -2,7 +2,7 @@ require 'neoid/middleware'
2
2
 
3
3
  module Neoid
4
4
  class Railtie < Rails::Railtie
5
- initializer "neoid.configure_rails_initialization" do
5
+ initializer 'neoid.configure_rails_initialization' do
6
6
  config.after_initialize do
7
7
  Neoid.initialize_all
8
8
  end
@@ -1,5 +1,70 @@
1
1
  module Neoid
2
2
  module Relationship
3
+ class << self
4
+ def from_hash(hash)
5
+ relationship = RelationshipLazyProxy.new(hash)
6
+
7
+ relationship
8
+ end
9
+
10
+ def included(receiver)
11
+ receiver.send :include, Neoid::ModelAdditions
12
+ receiver.send :include, InstanceMethods
13
+ receiver.extend ClassMethods
14
+
15
+ initialize_relationship receiver if Neoid.env_loaded
16
+
17
+ Neoid.relationship_models << receiver
18
+ end
19
+
20
+ def meta_data
21
+ @meta_data ||= {}
22
+ end
23
+
24
+ def initialize_relationship(rel_model)
25
+ rel_model.reflect_on_all_associations(:belongs_to).each do |belongs_to|
26
+ return if belongs_to.options[:polymorphic]
27
+
28
+ # e.g. all has_many on User class
29
+ all_has_many = belongs_to.klass.reflect_on_all_associations(:has_many)
30
+
31
+ # has_many (without through) on the side of the relationship that removes a relationship. e.g. User has_many :likes
32
+ this_has_many = all_has_many.find { |o| o.klass == rel_model }
33
+ next unless this_has_many
34
+
35
+ # e.g. User has_many :likes, after_remove: ...
36
+ full_callback_name = "after_remove_for_#{this_has_many.name}"
37
+ belongs_to.klass.send(full_callback_name) << :neo_after_relationship_remove if belongs_to.klass.method_defined?(full_callback_name)
38
+
39
+ # has_many (with through) on the side of the relationship that removes a relationship. e.g. User has_many :movies, through :likes
40
+ many_to_many = all_has_many.find { |o| o.options[:through] == this_has_many.name }
41
+ next unless many_to_many
42
+
43
+ return if many_to_many.options[:as] # polymorphic are not supported here yet
44
+
45
+ # user_id
46
+ foreign_key_of_owner = many_to_many.through_reflection.foreign_key
47
+
48
+ # movie_id
49
+ foreign_key_of_record = many_to_many.source_reflection.foreign_key
50
+
51
+ (Neoid::Relationship.meta_data ||= {}).tap do |data|
52
+ (data[belongs_to.klass.name.to_s] ||= {}).tap do |model_data|
53
+ model_data[many_to_many.klass.name.to_s] = [rel_model.name.to_s, foreign_key_of_owner, foreign_key_of_record]
54
+ end
55
+ end
56
+
57
+ # e.g. User has_many :movies, through: :likes, before_remove: ...
58
+ full_callback_name = "before_remove_for_#{many_to_many.name}"
59
+ belongs_to.klass.send(full_callback_name) << :neo_before_relationship_through_remove if belongs_to.klass.method_defined?(full_callback_name)
60
+
61
+ # e.g. User has_many :movies, through: :likes, after_remove: ...
62
+ full_callback_name = "after_remove_for_#{many_to_many.name}"
63
+ belongs_to.klass.send(full_callback_name) << :neo_after_relationship_through_remove if belongs_to.klass.method_defined?(full_callback_name)
64
+ end
65
+ end
66
+ end
67
+
3
68
  # this is a proxy that delays loading of start_node and end_node from Neo4j until accessed.
4
69
  # the original Neography Relatioship loaded them on initialization
5
70
  class RelationshipLazyProxy < ::Neography::Relationship
@@ -12,13 +77,6 @@ module Neoid
12
77
  end
13
78
  end
14
79
 
15
- def self.from_hash(hash)
16
- relationship = RelationshipLazyProxy.new(hash)
17
-
18
- relationship
19
- end
20
-
21
-
22
80
  module ClassMethods
23
81
  def delete_command
24
82
  :delete_relationship
@@ -27,26 +85,26 @@ module Neoid
27
85
 
28
86
  module InstanceMethods
29
87
  def neo_find_by_id
30
- results = Neoid.db.get_relationship_auto_index(Neoid::UNIQUE_ID_KEY, self.neo_unique_id)
88
+ results = Neoid.db.get_relationship_auto_index(Neoid::UNIQUE_ID_KEY, neo_unique_id)
31
89
  relationship = results.present? ? Neoid::Relationship.from_hash(results[0]) : nil
32
90
  relationship
33
91
  end
34
-
92
+
35
93
  def _neo_save
36
94
  return unless Neoid.enabled?
37
-
95
+
38
96
  options = self.class.neoid_config.relationship_options
39
-
40
- start_item = self.send(options[:start_node])
41
- end_item = self.send(options[:end_node])
42
-
97
+
98
+ start_item = send(options[:start_node])
99
+ end_item = send(options[:end_node])
100
+
43
101
  return unless start_item && end_item
44
102
 
45
103
  # initialize nodes
46
104
  start_item.neo_node
47
105
  end_item.neo_node
48
106
 
49
- data = self.to_neo.merge(ar_type: self.class.name, ar_id: self.id, Neoid::UNIQUE_ID_KEY => self.neo_unique_id)
107
+ data = to_neo.merge(ar_type: self.class.name, ar_id: id, Neoid::UNIQUE_ID_KEY => neo_unique_id)
50
108
  data.reject! { |k, v| v.nil? }
51
109
 
52
110
  rel_type = options[:type].is_a?(Proc) ? options[:type].call(self) : options[:type]
@@ -75,24 +133,24 @@ module Neoid
75
133
  relationship
76
134
  GREMLIN
77
135
 
78
- script_vars = {
136
+ script_vars = {
79
137
  unique_id_key: Neoid::UNIQUE_ID_KEY,
80
138
  relationship_data: data,
81
- unique_id: self.neo_unique_id,
139
+ unique_id: neo_unique_id,
82
140
  start_node_unique_id: start_item.neo_unique_id,
83
141
  end_node_unique_id: end_item.neo_unique_id,
84
142
  rel_type: rel_type
85
143
  }
86
144
 
87
- Neoid::logger.info "Relationship#neo_save #{self.class.name} #{self.id}"
88
-
145
+ Neoid::logger.info "Relationship#neo_save #{self.class.name} #{id}"
146
+
89
147
  relationship = Neoid.execute_script_or_add_to_batch gremlin_query, script_vars do |value|
90
148
  Neoid::Relationship.from_hash(value)
91
149
  end
92
150
 
93
151
  relationship
94
152
  end
95
-
153
+
96
154
  def neo_load(hash)
97
155
  Neoid::Relationship.from_hash(hash)
98
156
  end
@@ -101,63 +159,5 @@ module Neoid
101
159
  _neo_representation
102
160
  end
103
161
  end
104
-
105
- def self.included(receiver)
106
- receiver.send :include, Neoid::ModelAdditions
107
- receiver.send :include, InstanceMethods
108
- receiver.extend ClassMethods
109
-
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 ||= {}
117
- end
118
-
119
- def self.initialize_relationship(rel_model)
120
- rel_model.reflect_on_all_associations(:belongs_to).each do |belongs_to|
121
- return if belongs_to.options[:polymorphic]
122
-
123
- # e.g. all has_many on User class
124
- all_has_many = belongs_to.klass.reflect_on_all_associations(:has_many)
125
-
126
- # has_many (without through) on the side of the relationship that removes a relationship. e.g. User has_many :likes
127
- this_has_many = all_has_many.find { |o| o.klass == rel_model }
128
- next unless this_has_many
129
-
130
- # e.g. User has_many :likes, after_remove: ...
131
- full_callback_name = "after_remove_for_#{this_has_many.name}"
132
- belongs_to.klass.send(full_callback_name) << :neo_after_relationship_remove if belongs_to.klass.method_defined?(full_callback_name)
133
-
134
- # has_many (with through) on the side of the relationship that removes a relationship. e.g. User has_many :movies, through :likes
135
- many_to_many = all_has_many.find { |o| o.options[:through] == this_has_many.name }
136
- next unless many_to_many
137
-
138
- return if many_to_many.options[:as] # polymorphic are not supported here yet
139
-
140
- # user_id
141
- foreign_key_of_owner = many_to_many.through_reflection.foreign_key
142
-
143
- # movie_id
144
- foreign_key_of_record = many_to_many.source_reflection.foreign_key
145
-
146
- (Neoid::Relationship.meta_data ||= {}).tap do |data|
147
- (data[belongs_to.klass.name.to_s] ||= {}).tap do |model_data|
148
- model_data[many_to_many.klass.name.to_s] = [rel_model.name.to_s, foreign_key_of_owner, foreign_key_of_record]
149
- end
150
- end
151
-
152
- # e.g. User has_many :movies, through: :likes, before_remove: ...
153
- full_callback_name = "before_remove_for_#{many_to_many.name}"
154
- belongs_to.klass.send(full_callback_name) << :neo_before_relationship_through_remove if belongs_to.klass.method_defined?(full_callback_name)
155
-
156
-
157
- # e.g. User has_many :movies, through: :likes, after_remove: ...
158
- full_callback_name = "after_remove_for_#{many_to_many.name}"
159
- belongs_to.klass.send(full_callback_name) << :neo_after_relationship_through_remove if belongs_to.klass.method_defined?(full_callback_name)
160
- end
161
- end
162
162
  end
163
163
  end