neo4j 6.0.0.rc.4 → 6.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3dc2eaadf6662bef798f4f7eabb1b32c39ded0fe
4
- data.tar.gz: 07eea640b9818e8d77ef95f281be24fdbde658ca
3
+ metadata.gz: 5e75b34e6d901afdd9e426ecdb467541b6d89c28
4
+ data.tar.gz: ddc468292508fcfff1ad7371977503ec7a0274ae
5
5
  SHA512:
6
- metadata.gz: 0bd648f94fd9b1985d715576bd2568c878c3e34a8bfb07506e1dc38ea4a5b2d00a5f69f32f10689754e7263431356532cfb2869a088773209cf8cc970f0aab93
7
- data.tar.gz: 51497e8c6a42bdd565a08ab8ad0dcc540f5fce691199df458db002bba7d2eb7cea2a6b463d40fcfb2aecbf24ae8fc5807c558cefe9d7c6f249849dc0bf9cac4a
6
+ metadata.gz: 9cb421908fc3da97ba84eb9a7c5254a3f5d6568dd1bd9cdeadae15fdea333881113327a7710b1eb1094a2cb32a37330005653c97be07689ea194d64780add3bb
7
+ data.tar.gz: 8542d356502f221d0e054e913608aa1eb4134999495b309c589473f9c6850d4012096ef8c331f61c4c7880925b7634ecf525af1982d5160557b30f6ae07add9a
data/CHANGELOG.md CHANGED
@@ -3,6 +3,12 @@ All notable changes to this project will be documented in this file.
3
3
  This file should follow the standards specified on [http://keepachangelog.com/]
4
4
  This project adheres to [Semantic Versioning](http://semver.org/).
5
5
 
6
+ ## [Unreleased]
7
+
8
+ ### Fixed
9
+
10
+ - Refactor unpersisted association logic to store objects directly on the object rather than the association proxy since different association proxies may be created at different times (see #1043)
11
+
6
12
  ## [6.0.0.rc.4] - 11-19-2015
7
13
 
8
14
  ### Fixed
data/lib/neo4j.rb CHANGED
@@ -61,7 +61,6 @@ require 'neo4j/active_node/dependent'
61
61
  require 'neo4j/active_node/dependent/query_proxy_methods'
62
62
  require 'neo4j/active_node/dependent/association_methods'
63
63
  require 'neo4j/active_node/query_methods'
64
- require 'neo4j/active_node/query/query_proxy_unpersisted'
65
64
  require 'neo4j/active_node/query/query_proxy_methods'
66
65
  require 'neo4j/active_node/query/query_proxy_enumerable'
67
66
  require 'neo4j/active_node/query/query_proxy_find_in_batches'
@@ -50,6 +50,16 @@ module Neo4j
50
50
  _persisted_obj || fail('Tried to access native neo4j object on a non persisted object')
51
51
  end
52
52
 
53
+ module ClassMethods
54
+ def nodeify(object)
55
+ if object.is_a?(::Neo4j::ActiveNode) || object.nil?
56
+ object
57
+ else
58
+ self.find(object)
59
+ end
60
+ end
61
+ end
62
+
53
63
  included do
54
64
  include Neo4j::Timestamps if Neo4j::Config[:record_timestamps]
55
65
 
@@ -8,8 +8,10 @@ module Neo4j::ActiveNode
8
8
  # It uses a QueryProxy to get results
9
9
  # But also caches results and can have results cached on it
10
10
  class AssociationProxy
11
- def initialize(query_proxy, cached_result = nil)
11
+ def initialize(query_proxy, deferred_objects = [], cached_result = nil)
12
12
  @query_proxy = query_proxy
13
+ @deferred_objects = deferred_objects
14
+
13
15
  cache_result(cached_result)
14
16
 
15
17
  # Represents the thing which can be enumerated
@@ -48,21 +50,27 @@ module Neo4j::ActiveNode
48
50
  end
49
51
 
50
52
  def result
51
- return @cached_result if @cached_result
53
+ (@deferred_objects || []) + result_without_deferred
54
+ end
52
55
 
53
- cache_query_proxy_result
56
+ def result_without_deferred
57
+ cache_query_proxy_result if !@cached_result
54
58
 
55
59
  @cached_result
56
60
  end
57
61
 
58
62
  def result_nodes
59
- return result if !@query_proxy.model
63
+ return result_objects if !@query_proxy.model
60
64
 
61
- @cached_result = result.map do |object|
65
+ result_objects.map do |object|
62
66
  object.is_a?(Neo4j::ActiveNode) ? object : @query_proxy.model.find(object)
63
67
  end
64
68
  end
65
69
 
70
+ def result_objects
71
+ @deferred_objects + result_without_deferred
72
+ end
73
+
66
74
  def result_ids
67
75
  result.map do |object|
68
76
  object.is_a?(Neo4j::ActiveNode) ? object.id : object
@@ -80,9 +88,7 @@ module Neo4j::ActiveNode
80
88
  end
81
89
 
82
90
  def cache_query_proxy_result
83
- @query_proxy.to_a.tap do |result|
84
- cache_result(result)
85
- end
91
+ @query_proxy.to_a.tap { |result| cache_result(result) }
86
92
  end
87
93
 
88
94
  def clear_cache_result
@@ -93,6 +99,12 @@ module Neo4j::ActiveNode
93
99
  !!@cached_result
94
100
  end
95
101
 
102
+ def replace_with(*args)
103
+ @cached_result = nil
104
+
105
+ @query_proxy.public_send(:replace_with, *args)
106
+ end
107
+
96
108
  QUERY_PROXY_METHODS = [:<<, :delete]
97
109
  CACHED_RESULT_METHODS = []
98
110
 
@@ -177,7 +189,7 @@ module Neo4j::ActiveNode
177
189
  private
178
190
 
179
191
  def fresh_association_proxy(name, options = {}, cached_result = nil)
180
- AssociationProxy.new(association_query_proxy(name, options), cached_result)
192
+ AssociationProxy.new(association_query_proxy(name, options), deferred_nodes_for_association(name), cached_result)
181
193
  end
182
194
 
183
195
  def previous_proxy_results_by_previous_id(result_cache, association_name)
@@ -356,6 +368,8 @@ module Neo4j::ActiveNode
356
368
  define_method("#{name}=") do |other_nodes|
357
369
  association_proxy_cache.clear
358
370
 
371
+ clear_deferred_nodes_for_association(name)
372
+
359
373
  Neo4j::Transaction.run { association_proxy(name).replace_with(other_nodes) }
360
374
  end
361
375
  end
@@ -366,6 +380,7 @@ module Neo4j::ActiveNode
366
380
  end
367
381
 
368
382
  define_method_unless_defined("#{name.to_s.singularize}_ids=") do |ids|
383
+ clear_deferred_nodes_for_association(name)
369
384
  association_proxy(name).replace_with(ids)
370
385
  end
371
386
 
@@ -415,7 +430,13 @@ module Neo4j::ActiveNode
415
430
  if options[:rel_length] && !options[:rel_length].is_a?(Fixnum)
416
431
  association_proxy
417
432
  else
418
- association_proxy.result_nodes.first
433
+ target_class = self.class.send(:association_target_class, name)
434
+ o = association_proxy.result.first
435
+ if target_class
436
+ target_class.send(:nodeify, o)
437
+ else
438
+ o
439
+ end
419
440
  end
420
441
  end
421
442
  end
@@ -428,7 +449,8 @@ module Neo4j::ActiveNode
428
449
  Neo4j::Transaction.run { association_proxy(name).replace_with(other_node) }
429
450
  # handle_non_persisted_node(other_node)
430
451
  else
431
- association_proxy(name).defer_create(other_node)
452
+ defer_create(name, other_node, clear: true)
453
+ other_node
432
454
  end
433
455
  end
434
456
  end
@@ -457,8 +479,7 @@ module Neo4j::ActiveNode
457
479
  end
458
480
 
459
481
  def association_proxy(name, options = {})
460
- query_proxy = association_query_proxy(name, options)
461
- AssociationProxy.new(query_proxy)
482
+ AssociationProxy.new(association_query_proxy(name, options))
462
483
  end
463
484
 
464
485
  def association_target_class(name)
@@ -478,11 +499,8 @@ module Neo4j::ActiveNode
478
499
  end
479
500
 
480
501
  def default_association_query_proxy
481
- Neo4j::ActiveNode::Query::QueryProxy.new("::#{self.name}".constantize,
482
- nil,
483
- session: neo4j_session,
484
- query_proxy: nil,
485
- context: "#{self.name}")
502
+ Neo4j::ActiveNode::Query::QueryProxy.new("::#{self.name}".constantize, nil,
503
+ session: neo4j_session, query_proxy: nil, context: "#{self.name}")
486
504
  end
487
505
 
488
506
  def build_association(macro, direction, name, options)
@@ -85,10 +85,9 @@ module Neo4j::ActiveNode
85
85
  # build the processable hash before it begins. If there are nodes and associations that
86
86
  # need to be created after the node is saved, a new transaction is started.
87
87
  def cascade_save
88
- deferred_nodes = pending_associations_with_nodes
89
- Neo4j::Transaction.run(!deferred_nodes.blank?) do
88
+ Neo4j::Transaction.run(pending_deferred_creations?) do
90
89
  result = yield
91
- process_unpersisted_nodes!(deferred_nodes) if deferred_nodes
90
+ process_unpersisted_nodes!
92
91
  result
93
92
  end
94
93
  end
@@ -6,7 +6,6 @@ module Neo4j
6
6
  include Neo4j::ActiveNode::Query::QueryProxyMethods
7
7
  include Neo4j::ActiveNode::Query::QueryProxyFindInBatches
8
8
  include Neo4j::ActiveNode::Query::QueryProxyEagerLoading
9
- include Neo4j::ActiveNode::Query::QueryProxyUnpersisted
10
9
  include Neo4j::ActiveNode::Dependent::QueryProxyMethods
11
10
 
12
11
  # The most recent node to start a QueryProxy chain.
@@ -164,7 +163,13 @@ module Neo4j
164
163
 
165
164
  # To add a relationship for the node for the association on this QueryProxy
166
165
  def <<(other_node)
167
- @start_object._persisted_obj ? create(other_node, {}) : defer_create(other_node)
166
+ if @start_object._persisted_obj
167
+ create(other_node, {})
168
+ elsif @association
169
+ @start_object.defer_create(@association.name, other_node)
170
+ else
171
+ fail 'Another crazy error!'
172
+ end
168
173
  self
169
174
  end
170
175
 
@@ -1,52 +1,47 @@
1
1
  module Neo4j
2
2
  module ActiveNode
3
3
  module Unpersisted
4
- def pending_associations
5
- @pending_associations ||= []
4
+ # The values in this Hash are returned and used outside by reference
5
+ # so any modifications to the Array should be in-place
6
+ def deferred_create_cache
7
+ @deferred_create_cache ||= {}
6
8
  end
7
9
 
8
- def pending_associations?
9
- !@pending_associations.blank?
10
+ def defer_create(association_name, object, options = {})
11
+ clear_deferred_nodes_for_association(association_name) if options[:clear]
12
+
13
+ deferred_nodes_for_association(association_name) << object
10
14
  end
11
15
 
12
- private
16
+ def deferred_nodes_for_association(association_name)
17
+ deferred_create_cache[association_name.to_sym] ||= []
18
+ end
13
19
 
14
- # TODO: Change this method's name.
15
- # Takes the pending_associations hash, which is in the format { cache_key => [:association_name, :association_operator]},
16
- # and returns them as { association_name => [[nodes_for_persistence], :operator] }
17
- def pending_associations_with_nodes
18
- return unless pending_associations?
19
- {}.tap do |deferred_nodes|
20
- pending_associations.uniq.each do |association_name|
21
- nodes_for_creation = association_proxy(association_name)
22
- nodes_for_creation = nodes_for_creation.reject(&:persisted?) if self.persisted?
23
-
24
- deferred_nodes[association_name] = nodes_for_creation
25
- end
26
- end
20
+ def pending_deferred_creations?
21
+ !deferred_create_cache.values.all?(&:empty?)
27
22
  end
28
23
 
29
- # @param [Hash] deferred_nodes A hash created by :pending_associations_with_nodes
30
- def process_unpersisted_nodes!(deferred_nodes)
31
- deferred_nodes.each_pair do |k, v|
32
- save_and_associate_queue(k, v)
33
- end
24
+ def clear_deferred_nodes_for_association(association_name)
25
+ deferred_nodes_for_association(association_name.to_sym).clear
34
26
  end
35
27
 
28
+ private
36
29
 
37
- def save_and_associate_queue(association_name, node_queue)
38
- association_proc = proc { |node| save_and_associate_node(association_name, node) }
39
- node_queue.each do |element|
40
- element.is_a?(Array) ? element.each { |node| association_proc.call(node) } : association_proc.call(element)
41
- end
42
- end
30
+ def process_unpersisted_nodes!
31
+ deferred_create_cache.each do |association_name, nodes|
32
+ association_proxy = association_proxy(association_name)
33
+
34
+ nodes.each do |node|
35
+ if node.respond_to?(:changed?)
36
+ node.save if node.changed? || !node.persisted?
37
+ fail "Unable to defer node persistence, could not save #{node.inspect}" unless node.persisted?
38
+ end
39
+
40
+ association_proxy << node
41
+ end
43
42
 
44
- def save_and_associate_node(association_name, node)
45
- if node.respond_to?(:changed?)
46
- node.save if node.changed? || !node.persisted?
47
- fail "Unable to defer node persistence, could not save #{node.inspect}" unless node.persisted?
43
+ @deferred_create_cache = {}
48
44
  end
49
- association_proxy(association_name) << node
50
45
  end
51
46
  end
52
47
  end
data/lib/neo4j/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Neo4j
2
- VERSION = '6.0.0.rc.4'
2
+ VERSION = '6.0.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: neo4j
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.0.0.rc.4
4
+ version: 6.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andreas Ronge, Brian Underwood, Chris Grigg
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-19 00:00:00.000000000 Z
11
+ date: 2015-11-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: orm_adapter
@@ -251,7 +251,6 @@ files:
251
251
  - lib/neo4j/active_node/query/query_proxy_find_in_batches.rb
252
252
  - lib/neo4j/active_node/query/query_proxy_link.rb
253
253
  - lib/neo4j/active_node/query/query_proxy_methods.rb
254
- - lib/neo4j/active_node/query/query_proxy_unpersisted.rb
255
254
  - lib/neo4j/active_node/query_methods.rb
256
255
  - lib/neo4j/active_node/reflection.rb
257
256
  - lib/neo4j/active_node/rels.rb
@@ -327,9 +326,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
327
326
  version: 1.9.3
328
327
  required_rubygems_version: !ruby/object:Gem::Requirement
329
328
  requirements:
330
- - - ">"
329
+ - - ">="
331
330
  - !ruby/object:Gem::Version
332
- version: 1.3.1
331
+ version: '0'
333
332
  requirements: []
334
333
  rubyforge_project: neo4j
335
334
  rubygems_version: 2.4.5.1
@@ -1,13 +0,0 @@
1
- module Neo4j
2
- module ActiveNode
3
- module Query
4
- module QueryProxyUnpersisted
5
- def defer_create(other_node)
6
- @start_object.pending_associations << @association.name
7
-
8
- @start_object.association_proxy(@association.name).add_to_cache(other_node)
9
- end
10
- end
11
- end
12
- end
13
- end