activegraph 10.0.0.pre.alpha.7 → 10.0.0.pre.alpha.8
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 +4 -4
- data/CHANGELOG.md +6 -0
- data/config/neo4j/config.yml +0 -3
- data/lib/neo4j.rb +1 -0
- data/lib/neo4j/active_node.rb +1 -0
- data/lib/neo4j/active_node/dependent/query_proxy_methods.rb +12 -11
- data/lib/neo4j/active_node/dependent_callbacks.rb +31 -0
- data/lib/neo4j/active_node/has_n.rb +7 -8
- data/lib/neo4j/active_node/query/query_proxy.rb +1 -1
- data/lib/neo4j/active_node/query/query_proxy_methods_of_mass_updating.rb +29 -5
- data/lib/neo4j/active_rel/callbacks.rb +6 -0
- data/lib/neo4j/active_rel/persistence.rb +4 -5
- data/lib/neo4j/migrations/runner.rb +1 -1
- data/lib/neo4j/migrations/schema.rb +21 -1
- data/lib/neo4j/tasks/migration.rake +3 -1
- data/lib/neo4j/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6b7846af39d73f89f279284b358f2f4e5552709b6dd8812a5481944fdf479ec0
|
4
|
+
data.tar.gz: 71674f9403e7f9c88ab23631e138e6b901a3ae9dcfb672fbf7277ce20d26c61b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a0ed7a4862b179f5b0b02a3dbccc440604ab309e744736247c2d6600848f29387e9ecd4504a6a170a4dcc287be42543d6443d52d8a12ec4544a0b1238af796d5
|
7
|
+
data.tar.gz: fa3b8f1d9db6aa4c5d3d3090dd74a761a9d8c8399f0c1e5fcafeac57a6402b37f3987ee99efcf7a07e9a775b9f1045a574892e340b21d504b11fc39fb663a04e
|
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
|
+
## [10.0.x] 2020-01-23
|
7
|
+
|
8
|
+
- Executing relationship callbacks on relationship deletion.
|
9
|
+
- When assiging relationships, preserving earlier relationships.
|
10
|
+
- Enforcing has one constraint on relationships.
|
11
|
+
|
6
12
|
## [9.6.1] 2019-12-18
|
7
13
|
|
8
14
|
## Fixed
|
data/config/neo4j/config.yml
CHANGED
data/lib/neo4j.rb
CHANGED
@@ -61,6 +61,7 @@ require 'neo4j/active_rel/related_node'
|
|
61
61
|
require 'neo4j/active_rel/types'
|
62
62
|
require 'neo4j/active_rel'
|
63
63
|
|
64
|
+
require 'neo4j/active_node/dependent_callbacks'
|
64
65
|
require 'neo4j/active_node/node_list_formatter'
|
65
66
|
require 'neo4j/active_node/dependent'
|
66
67
|
require 'neo4j/active_node/dependent/query_proxy_methods'
|
data/lib/neo4j/active_node.rb
CHANGED
@@ -45,6 +45,7 @@ module Neo4j
|
|
45
45
|
include Neo4j::ActiveNode::Dependent
|
46
46
|
include Neo4j::ActiveNode::Enum
|
47
47
|
include Neo4j::Shared::PermittedAttributes
|
48
|
+
include Neo4j::ActiveNode::DependentCallbacks
|
48
49
|
|
49
50
|
def initialize(args = nil)
|
50
51
|
self.class.ensure_id_property_info! # So that we make sure all objects have an id_property
|
@@ -26,24 +26,25 @@ module Neo4j
|
|
26
26
|
# @param [String, Symbol] other_node The identifier to use for the other end of the chain.
|
27
27
|
# @param [String, Symbol] other_rel The identifier to use for the relationship in the optional match.
|
28
28
|
# @return [Neo4j::ActiveNode::Query::QueryProxy]
|
29
|
-
def unique_nodes(association, self_identifer, other_node, other_rel)
|
29
|
+
def unique_nodes(association, self_identifer, other_node, other_rel, ids = [])
|
30
30
|
fail 'Only supported by in QueryProxy chains started by an instance' unless source_object
|
31
31
|
return false if send(association.name).empty?
|
32
|
-
unique_nodes_query(association, self_identifer, other_node, other_rel)
|
32
|
+
unique_nodes_query(association, self_identifer, other_node, other_rel, ids)
|
33
33
|
.proxy_as(association.target_class, other_node)
|
34
34
|
end
|
35
35
|
|
36
36
|
private
|
37
37
|
|
38
|
-
def unique_nodes_query(association, self_identifer, other_node, other_rel)
|
39
|
-
query.with(identity).proxy_as_optional(source_object.class, self_identifer)
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
38
|
+
def unique_nodes_query(association, self_identifer, other_node, other_rel, ids)
|
39
|
+
base = query.with(identity).proxy_as_optional(source_object.class, self_identifer)
|
40
|
+
.send(association.name, other_node, other_rel)
|
41
|
+
base = base.where(id: ids) if ids.present?
|
42
|
+
base.query
|
43
|
+
.with(other_node)
|
44
|
+
.match("()#{association.arrow_cypher(:orphan_rel)}(#{other_node})")
|
45
|
+
.with(other_node, count: 'count(*)')
|
46
|
+
.where('count = $one', one: 1)
|
47
|
+
.break
|
47
48
|
end
|
48
49
|
end
|
49
50
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Neo4j
|
2
|
+
module ActiveNode
|
3
|
+
module DependentCallbacks
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
def dependent_delete_callback(association, ids)
|
7
|
+
association_query_proxy(association.name).where(id: ids).delete_all
|
8
|
+
end
|
9
|
+
|
10
|
+
def dependent_delete_orphans_callback(association, ids)
|
11
|
+
unique_query = as(:self).unique_nodes(association, :self, :n, :other_rel, ids)
|
12
|
+
unique_query.query.optional_match('(n)-[r]-()').delete(:n, :r).exec if unique_query
|
13
|
+
end
|
14
|
+
|
15
|
+
def dependent_destroy_callback(association, ids)
|
16
|
+
unique_query = association_query_proxy(association.name).where(id: ids)
|
17
|
+
unique_query.each_for_destruction(self, &:destroy) if unique_query
|
18
|
+
end
|
19
|
+
|
20
|
+
def dependent_destroy_orphans_callback(association, ids)
|
21
|
+
unique_query = as(:self).unique_nodes(association, :self, :n, :other_rel, ids)
|
22
|
+
unique_query.each_for_destruction(self, &:destroy) if unique_query
|
23
|
+
end
|
24
|
+
|
25
|
+
def callbacks_from_active_rel(active_rel, direction, other_node)
|
26
|
+
rel = active_rel_corresponding_rel(active_rel, direction, other_node.class).try(:last)
|
27
|
+
public_send("dependent_#{rel.dependent}_callback", rel, [other_node.id]) if rel && rel.dependent
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -229,10 +229,9 @@ module Neo4j::ActiveNode
|
|
229
229
|
end
|
230
230
|
end
|
231
231
|
|
232
|
-
def
|
233
|
-
return unless Neo4j::Config[:enforce_has_one]
|
232
|
+
def delete_reverse_has_one_core_rel(association)
|
234
233
|
reverse_assoc = reverse_association(association)
|
235
|
-
|
234
|
+
delete_has_one_rel!(reverse_assoc) if reverse_assoc && reverse_assoc.type == :has_one
|
236
235
|
end
|
237
236
|
|
238
237
|
def reverse_association(association)
|
@@ -242,14 +241,14 @@ module Neo4j::ActiveNode
|
|
242
241
|
reverse_assoc && reverse_assoc.last
|
243
242
|
end
|
244
243
|
|
245
|
-
def
|
244
|
+
def delete_reverse_has_one_active_rel(active_rel, direction, other_node)
|
246
245
|
rel = active_rel_corresponding_rel(active_rel, direction, other_node.class)
|
247
|
-
|
246
|
+
delete_has_one_rel!(rel.last) if rel && rel.last.type == :has_one
|
248
247
|
end
|
249
248
|
|
250
|
-
def
|
251
|
-
|
252
|
-
|
249
|
+
def delete_has_one_rel!(rel)
|
250
|
+
send("#{rel.name}", :n, :r, chainable: true).query.delete(:r).exec
|
251
|
+
association_proxy_cache.clear
|
253
252
|
end
|
254
253
|
|
255
254
|
def active_rel_corresponding_rel(active_rel, direction, target_class)
|
@@ -208,7 +208,7 @@ module Neo4j
|
|
208
208
|
Neo4j::ActiveBase.run_transaction do
|
209
209
|
other_nodes.each do |other_node|
|
210
210
|
if other_node.neo_id
|
211
|
-
other_node.try(:
|
211
|
+
other_node.try(:delete_reverse_has_one_core_rel, association)
|
212
212
|
else
|
213
213
|
other_node.save
|
214
214
|
end
|
@@ -49,13 +49,37 @@ module Neo4j
|
|
49
49
|
# Deletes the relationships between all nodes for the last step in the QueryProxy chain and replaces them with relationships to the given nodes.
|
50
50
|
# Executed in the database, callbacks will not be run.
|
51
51
|
def replace_with(node_or_nodes)
|
52
|
-
|
52
|
+
node_hash = idify_hash(node_or_nodes)
|
53
|
+
original_ids = self.pluck(:id)
|
54
|
+
new_nodes = add_rels(node_hash, original_ids)
|
55
|
+
delete_rels_for_nodes(original_ids - node_hash.keys)
|
56
|
+
new_nodes | node_hash.values
|
57
|
+
end
|
58
|
+
|
59
|
+
def idify_hash(args)
|
60
|
+
Array(args).reject(&:blank?).flatten.each_with_object({}).with_index do |(arg, hash), inx|
|
61
|
+
if arg.is_a?(Integer) || arg.is_a?(String)
|
62
|
+
hash[arg.to_i] = @model.find(arg)
|
63
|
+
else
|
64
|
+
key = arg.persisted? ? arg.id : "tmp_#{inx}"
|
65
|
+
hash[key] = arg
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
53
69
|
|
54
|
-
|
55
|
-
|
56
|
-
|
70
|
+
def add_rels(node_hash, original_ids)
|
71
|
+
(node_hash.keys - original_ids).map do |id|
|
72
|
+
node_hash[id] if _create_relation_or_defer(node_hash[id])
|
57
73
|
end.compact
|
58
|
-
|
74
|
+
end
|
75
|
+
|
76
|
+
def delete_rels_for_nodes(ids)
|
77
|
+
return unless ids.present?
|
78
|
+
if association.dependent
|
79
|
+
start_object.public_send("dependent_#{association.dependent}_callback", association, ids)
|
80
|
+
else
|
81
|
+
self.where(id: ids).delete_all_rels
|
82
|
+
end
|
59
83
|
end
|
60
84
|
|
61
85
|
# Returns all relationships between a node and its last link in the QueryProxy chain, destroys them in Ruby. Callbacks will be run.
|
@@ -45,17 +45,16 @@ module Neo4j::ActiveRel
|
|
45
45
|
|
46
46
|
def create_model
|
47
47
|
validate_node_classes!
|
48
|
-
|
48
|
+
delete_has_one_rel
|
49
49
|
rel = _create_rel
|
50
50
|
return self unless rel.respond_to?(:props)
|
51
51
|
init_on_load(rel, from_node, to_node, @rel_type)
|
52
52
|
true
|
53
53
|
end
|
54
54
|
|
55
|
-
def
|
56
|
-
|
57
|
-
|
58
|
-
from_node.validate_reverse_has_one_active_rel(self, :out, to_node) if from_node.persisted?
|
55
|
+
def delete_has_one_rel
|
56
|
+
to_node.delete_reverse_has_one_active_rel(self, :in, from_node) if to_node.persisted?
|
57
|
+
from_node.delete_reverse_has_one_active_rel(self, :out, to_node) if from_node.persisted?
|
59
58
|
end
|
60
59
|
|
61
60
|
def query_as(var)
|
@@ -58,7 +58,7 @@ module Neo4j
|
|
58
58
|
|
59
59
|
def mark_versions_as_complete(versions)
|
60
60
|
Neo4j::ActiveBase.new_query
|
61
|
-
.with('
|
61
|
+
.with('$versions AS versions').params(versions: versions).break
|
62
62
|
.unwind(version: :versions).break
|
63
63
|
.merge('(:`Neo4j::Migrations::SchemaMigration` {migration_id: version})')
|
64
64
|
.exec
|
@@ -23,12 +23,32 @@ module Neo4j
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def fetch_index_descriptions(session)
|
26
|
-
session.query('CALL db.indexes()')
|
26
|
+
result = session.query('CALL db.indexes()')
|
27
|
+
if result.columns.include?(:description)
|
28
|
+
v3_indexes(result)
|
29
|
+
else
|
30
|
+
v4_indexes(result)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def v3_indexes(result)
|
35
|
+
result.reject do |row|
|
27
36
|
# These indexes are created automagically when the corresponding constraints are created
|
28
37
|
row.type == 'node_unique_property'
|
29
38
|
end.map(&:description)
|
30
39
|
end
|
31
40
|
|
41
|
+
def v4_indexes(result)
|
42
|
+
result.reject do |row|
|
43
|
+
# These indexes are created automagically when the corresponding constraints are created
|
44
|
+
row.uniqueness == 'UNIQUE'
|
45
|
+
end.map(&method(:description))
|
46
|
+
end
|
47
|
+
|
48
|
+
def description(row)
|
49
|
+
"INDEX FOR (n:#{row.labelsOrTypes.first}) ON (#{row.properties.map{|prop| "n.#{prop}"}.join(', ')})"
|
50
|
+
end
|
51
|
+
|
32
52
|
def drop_and_create_queries(existing, specified, remove_missing)
|
33
53
|
[].tap do |queries|
|
34
54
|
if remove_missing
|
@@ -97,11 +97,13 @@ COMMENT
|
|
97
97
|
|
98
98
|
schema_data = YAML.safe_load(File.read(SCHEMA_YAML_PATH), [Symbol])
|
99
99
|
|
100
|
-
Neo4j::
|
100
|
+
Neo4j::Transaction.subscribe_to_query(&method(:puts))
|
101
101
|
|
102
102
|
Neo4j::ActiveBase.run_transaction do
|
103
103
|
Neo4j::Migrations::Schema.synchronize_schema_data(Neo4j::ActiveBase.transaction, schema_data, args[:remove_missing])
|
104
|
+
end
|
104
105
|
|
106
|
+
Neo4j::ActiveBase.run_transaction do
|
105
107
|
runner = Neo4j::Migrations::Runner.new
|
106
108
|
runner.mark_versions_as_complete(schema_data[:versions]) # Run in test mode?
|
107
109
|
end
|
data/lib/neo4j/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activegraph
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 10.0.0.pre.alpha.
|
4
|
+
version: 10.0.0.pre.alpha.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andreas Ronge, Brian Underwood, Chris Grigg, Heinrich Klobuczek
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-02-
|
11
|
+
date: 2020-02-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -259,6 +259,7 @@ files:
|
|
259
259
|
- lib/neo4j/active_node/dependent.rb
|
260
260
|
- lib/neo4j/active_node/dependent/association_methods.rb
|
261
261
|
- lib/neo4j/active_node/dependent/query_proxy_methods.rb
|
262
|
+
- lib/neo4j/active_node/dependent_callbacks.rb
|
262
263
|
- lib/neo4j/active_node/enum.rb
|
263
264
|
- lib/neo4j/active_node/has_n.rb
|
264
265
|
- lib/neo4j/active_node/has_n/association.rb
|