activegraph 10.1.0 → 11.1.0.alpha.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/Gemfile +1 -1
- data/README.md +24 -20
- data/activegraph.gemspec +2 -2
- data/lib/active_graph/base.rb +1 -1
- data/lib/active_graph/core/label.rb +3 -2
- data/lib/active_graph/core/querable.rb +6 -20
- data/lib/active_graph/core/query_builder.rb +9 -21
- data/lib/active_graph/core/result.rb +14 -13
- data/lib/active_graph/core/schema.rb +26 -18
- data/lib/active_graph/core.rb +1 -1
- data/lib/active_graph/errors.rb +2 -0
- data/lib/active_graph/migrations/base.rb +6 -3
- data/lib/active_graph/migrations/schema.rb +13 -11
- data/lib/active_graph/node/has_n.rb +4 -2
- data/lib/active_graph/node/query/query_proxy_eager_loading/association_tree.rb +1 -0
- data/lib/active_graph/node/query/query_proxy_eager_loading.rb +3 -9
- data/lib/active_graph/secure_random_ext.rb +13 -0
- data/lib/active_graph/shared/persistence.rb +2 -2
- data/lib/active_graph/shared/property.rb +1 -1
- data/lib/active_graph/tasks/migration.rake +16 -30
- data/lib/active_graph/transaction.rb +3 -8
- data/lib/active_graph/transactions.rb +18 -17
- data/lib/active_graph/version.rb +1 -1
- data/lib/active_graph.rb +2 -0
- metadata +21 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 62237e7dafd589f3a2abe8180ada5c30b7bc12dffa5e165c428dfb4c4a25af7b
|
4
|
+
data.tar.gz: 002ef52d6ad7e0f6735db23c37b033dc24df6af2e0ddd116d593ed88f21f00a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4657e85cf211773ba1749e475b1110476fab90a312bb5233f78ca459653ef477090d7c38753390948afb539e21bd831a9960c1395dbbee5f15d0fcb3b40f3f91
|
7
|
+
data.tar.gz: 8023fed0a8ae2ab3b84aa6c76ba0aecbe3ed9d93bbf2d70b094c91afdb1e9a459927dd5f473a046fd7b3ccb45a85b833bb775b9ed4c9374fd9cee06ba182735e
|
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,22 @@ 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
|
+
## [11.0.2] 2021-11-05
|
7
|
+
|
8
|
+
## Fixed
|
9
|
+
|
10
|
+
- Fixed issue where some has_one relationships where incorrectly deleted disregarding direction
|
11
|
+
|
12
|
+
## [11.0.1] 2021-07-14
|
13
|
+
|
14
|
+
- It changes the relationship length assignment in query proxy eagerloading module to be consistent with query proxy relationship length syntax.
|
15
|
+
|
16
|
+
## [11.0.0] 2021-06-25
|
17
|
+
|
18
|
+
## Added
|
19
|
+
|
20
|
+
- support for neo4j 4.1, 4.2, 4.3
|
21
|
+
|
6
22
|
## [10.1.0] 2021-02-05
|
7
23
|
|
8
24
|
## Added
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -45,31 +45,35 @@ Neo4j.rb v4.1.0 was released in January of 2015. Its changes are outlined [here]
|
|
45
45
|
|
46
46
|
## Neo4j version support
|
47
47
|
|
48
|
-
| **Neo4j Version** | v2.x | v3.x | >= v4.x | >= 7.0.3 | activegraph 10
|
49
|
-
|
50
|
-
| 1.9.x | Yes | No | No | No | No |
|
51
|
-
| 2.0.x | No | Yes | No | No | No |
|
52
|
-
| 2.1.x | No | Yes | Yes * | Yes | No |
|
53
|
-
| 2.2.x | No | No | Yes | Yes | No |
|
54
|
-
| 2.3.x | No | No | Yes | Yes | No |
|
55
|
-
| 3.0, 3.1, 3.3 | No | No | No | Yes | No |
|
56
|
-
| 3.4
|
57
|
-
|
|
58
|
-
| 4.
|
48
|
+
| **Neo4j Version** | v2.x | v3.x | >= v4.x | >= 7.0.3 | activegraph 10 | activegraph 11 (jRuby only) |
|
49
|
+
|-------------------|------|-------|---------|----------|------------------|-----------------------------|
|
50
|
+
| 1.9.x | Yes | No | No | No | No | No
|
51
|
+
| 2.0.x | No | Yes | No | No | No | No
|
52
|
+
| 2.1.x | No | Yes | Yes * | Yes | No | No
|
53
|
+
| 2.2.x | No | No | Yes | Yes | No | No
|
54
|
+
| 2.3.x | No | No | Yes | Yes | No | No
|
55
|
+
| 3.0, 3.1, 3.3 | No | No | No | Yes | No | No
|
56
|
+
| 3.4 | No | No | No | Yes | Yes | No
|
57
|
+
| 3.5 | No | No | No | Yes | Yes | Yes
|
58
|
+
| 4.0 | No | No | No | No | Yes | Yes
|
59
|
+
| 4.1 | No | No | No | No | No | Yes
|
60
|
+
| 4.2 | No | No | No | No | No | Yes
|
61
|
+
| 4.3 | No | No | No | No | No | Yes
|
62
|
+
| 4.4 | No | No | No | No | No | Yes
|
59
63
|
|
60
64
|
`*` Neo4j.rb >= 4.x doesn't support Neo4j versions before 2.1.5. To use 2.1.x you should upgrade to a version >= 2.1.5
|
61
65
|
|
62
66
|
## Neo4j feature support
|
63
67
|
|
64
|
-
| **Neo4j Feature** | v2.x | v3.x | >= v4.x | >= 8.x | activegraph 10.0 |
|
65
|
-
|
66
|
-
| Bolt Protocol | No | No | No | Yes | Yes
|
67
|
-
| Auth | No | No | Yes | Yes | Yes
|
68
|
-
| Remote Cypher | Yes | Yes | Yes | Yes | No
|
69
|
-
| Transactions | Yes | Yes | Yes | Yes | Yes
|
70
|
-
| High Availability | No | Yes | Yes | Yes | Yes
|
71
|
-
| Causal Cluster | No | No | No | No | Yes
|
72
|
-
| Embedded JVM support | Yes | Yes | Yes | Yes | via bolt only
|
68
|
+
| **Neo4j Feature** | v2.x | v3.x | >= v4.x | >= 8.x | >= activegraph 10.0 |
|
69
|
+
|----------------------------|--------|------|---------|--------|---------------------|
|
70
|
+
| Bolt Protocol | No | No | No | Yes | Yes |
|
71
|
+
| Auth | No | No | Yes | Yes | Yes |
|
72
|
+
| Remote Cypher | Yes | Yes | Yes | Yes | No |
|
73
|
+
| Transactions | Yes | Yes | Yes | Yes | Yes |
|
74
|
+
| High Availability | No | Yes | Yes | Yes | Yes |
|
75
|
+
| Causal Cluster | No | No | No | No | Yes |
|
76
|
+
| Embedded JVM support | Yes | Yes | Yes | Yes | via bolt only |
|
73
77
|
|
74
78
|
## Documentation
|
75
79
|
|
data/activegraph.gemspec
CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |s|
|
|
7
7
|
s.name = 'activegraph'
|
8
8
|
s.version = ActiveGraph::VERSION
|
9
9
|
|
10
|
-
s.required_ruby_version = '>= 2.
|
10
|
+
s.required_ruby_version = '>= 2.6'
|
11
11
|
|
12
12
|
s.authors = 'Andreas Ronge, Brian Underwood, Chris Grigg, Heinrich Klobuczek'
|
13
13
|
s.email = 'andreas.ronge@gmail.com, public@brian-underwood.codes, chris@subvertallmedia.com, heinrich@mail.com'
|
@@ -33,13 +33,13 @@ DESCRIPTION
|
|
33
33
|
s.add_dependency('activemodel', '>= 4.0')
|
34
34
|
s.add_dependency('activesupport', '>= 4.0')
|
35
35
|
s.add_dependency('i18n', '!= 1.8.8') # https://github.com/jruby/jruby/issues/6547
|
36
|
+
s.add_dependency('neo4j-ruby-driver', '>= 4.4.0.alpha.5')
|
36
37
|
s.add_dependency('orm_adapter', '~> 0.5.0')
|
37
38
|
s.add_dependency('sorted_set')
|
38
39
|
s.add_development_dependency('guard')
|
39
40
|
s.add_development_dependency('guard-rspec')
|
40
41
|
s.add_development_dependency('guard-rubocop')
|
41
42
|
s.add_development_dependency('neo4j-rake_tasks', '>= 0.3.0')
|
42
|
-
s.add_development_dependency("neo4j-#{ENV['driver'] == 'java' ? 'java' : 'ruby'}-driver", '~> 1.7.4')
|
43
43
|
s.add_development_dependency('os')
|
44
44
|
s.add_development_dependency('pry')
|
45
45
|
s.add_development_dependency('railties', '>= 4.0')
|
data/lib/active_graph/base.rb
CHANGED
@@ -114,8 +114,9 @@ module ActiveGraph
|
|
114
114
|
end
|
115
115
|
|
116
116
|
def drop_constraints
|
117
|
-
ActiveGraph::Base.
|
118
|
-
|
117
|
+
result = ActiveGraph::Base.read_transaction { |tx| tx.run('CALL db.constraints').to_a }
|
118
|
+
ActiveGraph::Base.write_transaction do |tx|
|
119
|
+
result.each do |record|
|
119
120
|
tx.run("DROP #{record.keys.include?(:name) ? "CONSTRAINT #{record[:name]}" : record[:description]}")
|
120
121
|
end
|
121
122
|
end
|
@@ -18,34 +18,20 @@ module ActiveGraph
|
|
18
18
|
args.pop if args[0].is_a?(::ActiveGraph::Core::Query)
|
19
19
|
end || {}
|
20
20
|
|
21
|
-
|
21
|
+
query_run(QueryBuilder.query(*args), options)
|
22
22
|
end
|
23
23
|
|
24
|
-
def
|
25
|
-
query_builder = QueryBuilder.new
|
26
|
-
|
27
|
-
query_builder.instance_eval(&block)
|
28
|
-
|
29
|
-
transaction do
|
30
|
-
query_set(query_builder.queries, options)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def setup_queries!(queries, options = {})
|
24
|
+
def setup_query!(query, options = {})
|
35
25
|
return if options[:skip_instrumentation]
|
36
|
-
|
37
|
-
ActiveSupport::Notifications.instrument('neo4j.core.cypher_query', query: query)
|
38
|
-
end
|
26
|
+
ActiveSupport::Notifications.instrument('neo4j.core.cypher_query', query: query)
|
39
27
|
end
|
40
28
|
|
41
|
-
def
|
42
|
-
|
29
|
+
def query_run(query, options = {})
|
30
|
+
setup_query!(query, skip_instrumentation: options[:skip_instrumentation])
|
43
31
|
|
44
32
|
ActiveSupport::Notifications.instrument('neo4j.core.bolt.request') do
|
45
33
|
transaction do |tx|
|
46
|
-
|
47
|
-
tx.run(query.cypher, query.parameters).tap { |result| result.wrap = options[:wrap] != false }
|
48
|
-
end
|
34
|
+
tx.run(query.cypher, **query.parameters).tap { |result| result.wrap = options[:wrap] != false }
|
49
35
|
end
|
50
36
|
end
|
51
37
|
end
|
@@ -1,29 +1,17 @@
|
|
1
1
|
module ActiveGraph
|
2
2
|
module Core
|
3
3
|
class QueryBuilder
|
4
|
-
attr_reader :queries
|
5
|
-
|
6
4
|
Query = Struct.new(:cypher, :parameters, :pretty_cypher, :context)
|
7
5
|
|
8
|
-
def
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
args[0]
|
18
|
-
else
|
19
|
-
fail ArgumentError, "Could not determine query from arguments: #{args.inspect}"
|
20
|
-
end
|
21
|
-
|
22
|
-
@queries << query
|
23
|
-
end
|
24
|
-
|
25
|
-
def query
|
26
|
-
ActiveGraph::Core::Query.new
|
6
|
+
def self.query(*args)
|
7
|
+
case args.map(&:class)
|
8
|
+
when [String], [String, Hash]
|
9
|
+
Query.new(args[0], args[1] || {})
|
10
|
+
when [::ActiveGraph::Core::Query]
|
11
|
+
args[0]
|
12
|
+
else
|
13
|
+
fail ArgumentError, "Could not determine query from arguments: #{args.inspect}"
|
14
|
+
end
|
27
15
|
end
|
28
16
|
end
|
29
17
|
end
|
@@ -3,26 +3,27 @@ module ActiveGraph
|
|
3
3
|
module Result
|
4
4
|
attr_writer :wrap
|
5
5
|
|
6
|
+
def keys
|
7
|
+
@keys ||= super
|
8
|
+
end
|
9
|
+
|
6
10
|
def wrap?
|
7
11
|
@wrap
|
8
12
|
end
|
9
13
|
|
10
14
|
def each(&block)
|
11
|
-
wrap? ?
|
15
|
+
store if wrap? # TODO: why? This is preventing streaming
|
16
|
+
@records&.each(&block) || super
|
12
17
|
end
|
13
18
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
record.wrap = wrap?
|
23
|
-
@records << record
|
24
|
-
block_given? ? yield(record) : record
|
25
|
-
end
|
19
|
+
def store
|
20
|
+
return if @records
|
21
|
+
keys
|
22
|
+
@records = []
|
23
|
+
# TODO: implement 'each' without block parameter
|
24
|
+
method(:each).super_method.call do |record|
|
25
|
+
record.wrap = wrap?
|
26
|
+
@records << record
|
26
27
|
end
|
27
28
|
end
|
28
29
|
end
|
@@ -2,25 +2,33 @@ module ActiveGraph
|
|
2
2
|
module Core
|
3
3
|
module Schema
|
4
4
|
def version
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
read_transaction do
|
6
|
+
# BTW: community / enterprise could be retrieved via `result.first.edition`
|
7
|
+
query('CALL dbms.components()', {}, skip_instrumentation: true).first[:versions][0]
|
8
|
+
end
|
9
9
|
end
|
10
10
|
|
11
11
|
def indexes
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
raw_indexes do |keys, result|
|
13
|
+
result.map do |row|
|
14
|
+
{ type: row[:type].to_sym, label: label(keys, row), properties: properties(row),
|
15
|
+
state: row[:state].to_sym }
|
16
|
+
end
|
16
17
|
end
|
17
18
|
end
|
18
19
|
|
19
20
|
def constraints
|
20
|
-
|
21
|
+
raw_indexes do |keys, result|
|
22
|
+
result.select(&method(v4?(keys) ? :v4_filter : :v3_filter)).map do |row|
|
23
|
+
{ type: :uniqueness, label: label(keys, row), properties: properties(row) }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
21
27
|
|
22
|
-
|
23
|
-
|
28
|
+
def raw_indexes
|
29
|
+
read_transaction do
|
30
|
+
result = query('CALL db.indexes()', {}, skip_instrumentation: true)
|
31
|
+
yield result.keys, result.reject { |row| row[:type] == 'LOOKUP' }
|
24
32
|
end
|
25
33
|
end
|
26
34
|
|
@@ -34,22 +42,22 @@ module ActiveGraph
|
|
34
42
|
row[:type] == 'node_unique_property'
|
35
43
|
end
|
36
44
|
|
37
|
-
def label(
|
38
|
-
if v34?(
|
45
|
+
def label(keys, row)
|
46
|
+
if v34?(keys)
|
39
47
|
row[:label]
|
40
48
|
else
|
41
|
-
(v4?(
|
49
|
+
(v4?(keys) ? row[:labelsOrTypes] : row[:tokenNames]).first
|
42
50
|
end.to_sym
|
43
51
|
end
|
44
52
|
|
45
|
-
def v4?(
|
53
|
+
def v4?(keys)
|
46
54
|
return @v4 unless @v4.nil?
|
47
|
-
@v4 =
|
55
|
+
@v4 = keys.include?(:labelsOrTypes)
|
48
56
|
end
|
49
57
|
|
50
|
-
def v34?(
|
58
|
+
def v34?(keys)
|
51
59
|
return @v34 unless @v34.nil?
|
52
|
-
@v34 =
|
60
|
+
@v34 = keys.include?(:label)
|
53
61
|
end
|
54
62
|
|
55
63
|
def properties(row)
|
data/lib/active_graph/core.rb
CHANGED
@@ -10,5 +10,5 @@ require 'neo4j_ruby_driver'
|
|
10
10
|
Neo4j::Driver::Types::Entity.include ActiveGraph::Core::Wrappable
|
11
11
|
Neo4j::Driver::Types::Entity.prepend ActiveGraph::Core::Entity
|
12
12
|
Neo4j::Driver::Types::Node.prepend ActiveGraph::Core::Node
|
13
|
-
Neo4j::Driver::
|
13
|
+
Neo4j::Driver::Result.prepend ActiveGraph::Core::Result
|
14
14
|
Neo4j::Driver::Record.prepend ActiveGraph::Core::Record
|
data/lib/active_graph/errors.rb
CHANGED
@@ -57,9 +57,12 @@ module ActiveGraph
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def handle_migration_error!(e)
|
60
|
-
|
61
|
-
|
62
|
-
|
60
|
+
if e.is_a?(Neo4j::Driver::Exceptions::ClientException) &&
|
61
|
+
e.code == 'Neo.ClientError.Transaction.ForbiddenDueToTransactionType'
|
62
|
+
fail MigrationError, "#{e.message}. Please add `disable_transactions!` in your migration file."
|
63
|
+
else
|
64
|
+
fail e
|
65
|
+
end
|
63
66
|
end
|
64
67
|
|
65
68
|
def migration_transaction(&block)
|
@@ -3,16 +3,17 @@ module ActiveGraph
|
|
3
3
|
module Schema
|
4
4
|
class << self
|
5
5
|
def fetch_schema_data
|
6
|
-
{constraints: fetch_constraint_descriptions.sort,
|
7
|
-
indexes: fetch_index_descriptions.sort}
|
6
|
+
{ constraints: fetch_constraint_descriptions.sort, indexes: fetch_index_descriptions.sort }
|
8
7
|
end
|
9
8
|
|
10
9
|
def synchronize_schema_data(schema_data, remove_missing)
|
11
10
|
queries = []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
ActiveGraph::Base.read_transaction do
|
12
|
+
queries += drop_and_create_queries(fetch_constraint_descriptions, schema_data[:constraints], remove_missing)
|
13
|
+
queries += drop_and_create_queries(fetch_index_descriptions, schema_data[:indexes], remove_missing)
|
14
|
+
end
|
15
|
+
ActiveGraph::Base.write_transaction do
|
16
|
+
queries.each(&ActiveGraph::Base.method(:query))
|
16
17
|
end
|
17
18
|
end
|
18
19
|
|
@@ -23,11 +24,12 @@ module ActiveGraph
|
|
23
24
|
end
|
24
25
|
|
25
26
|
def fetch_index_descriptions
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
27
|
+
ActiveGraph::Base.raw_indexes do |keys, result|
|
28
|
+
if keys.include?(:description)
|
29
|
+
v3_indexes(result)
|
30
|
+
else
|
31
|
+
v4_indexes(result)
|
32
|
+
end
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|
@@ -253,8 +253,10 @@ module ActiveGraph::Node
|
|
253
253
|
|
254
254
|
def relationship_corresponding_rel(relationship, direction, target_class)
|
255
255
|
self.class.associations.find do |_key, assoc|
|
256
|
-
assoc.
|
257
|
-
|
256
|
+
assoc.direction == direction && (
|
257
|
+
assoc.relationship_class_name == relationship.class.name ||
|
258
|
+
(assoc.relationship_type == relationship.type.to_sym && assoc.target_class == target_class)
|
259
|
+
)
|
258
260
|
end
|
259
261
|
end
|
260
262
|
|
@@ -68,7 +68,7 @@ module ActiveGraph
|
|
68
68
|
|
69
69
|
def init_associations(node, element)
|
70
70
|
element.each_key { |key| node.association_proxy(key).init_cache }
|
71
|
-
node.association_proxy(element.name).init_cache if element.rel_length == ''
|
71
|
+
node.association_proxy(element.name).init_cache if element.rel_length && element.rel_length[:max] == ''
|
72
72
|
end
|
73
73
|
|
74
74
|
def cache_and_init(node, element)
|
@@ -157,14 +157,8 @@ module ActiveGraph
|
|
157
157
|
end
|
158
158
|
|
159
159
|
def relationship_part(association, path_name, rel_length)
|
160
|
-
|
161
|
-
|
162
|
-
length = {max: rel_length}
|
163
|
-
else
|
164
|
-
rel_name = escape("#{path_name}_rel")
|
165
|
-
length = nil
|
166
|
-
end
|
167
|
-
"#{association.arrow_cypher(rel_name, {}, false, false, length)}(#{escape(path_name)})"
|
160
|
+
rel_name = escape("#{path_name}_rel") unless rel_length
|
161
|
+
"#{association.arrow_cypher(rel_name, {}, false, false, rel_length)}(#{escape(path_name)})"
|
168
162
|
end
|
169
163
|
|
170
164
|
def chain
|
@@ -90,7 +90,7 @@ module ActiveGraph::Shared
|
|
90
90
|
apply_default_values
|
91
91
|
result = _persisted_obj ? update_model : create_model
|
92
92
|
|
93
|
-
ActiveGraph::Base.transaction(&:
|
93
|
+
ActiveGraph::Base.transaction(&:rollback) if result == false
|
94
94
|
|
95
95
|
result != false
|
96
96
|
ensure
|
@@ -179,7 +179,7 @@ module ActiveGraph::Shared
|
|
179
179
|
ActiveGraph::Base.transaction do |tx|
|
180
180
|
self.attributes = process_attributes(attributes)
|
181
181
|
saved = save
|
182
|
-
tx.
|
182
|
+
tx.rollback unless saved
|
183
183
|
saved
|
184
184
|
end
|
185
185
|
end
|
@@ -12,7 +12,7 @@ module ActiveGraph::Shared
|
|
12
12
|
attr_reader :_persisted_obj
|
13
13
|
|
14
14
|
# This list should not be statically created. All types which have converters should by type casted
|
15
|
-
NEO4J_DRIVER_DATA_TYPES = [Hash,
|
15
|
+
NEO4J_DRIVER_DATA_TYPES = [Hash, ActiveSupport::Duration, Neo4j::Driver::Types::Point,
|
16
16
|
Neo4j::Driver::Types::OffsetTime, Neo4j::Driver::Types::LocalTime, Neo4j::Driver::Types::LocalDateTime]
|
17
17
|
|
18
18
|
# TODO: Set @attribute correctly using class ActiveModel::Attribute, and after that
|
@@ -62,50 +62,36 @@ namespace :neo4j do
|
|
62
62
|
|
63
63
|
COMMENT
|
64
64
|
|
65
|
-
def check_neo4j_version_3
|
66
|
-
if ActiveGraph::Base.version > '3.0.0'
|
67
|
-
yield
|
68
|
-
else
|
69
|
-
puts 'WARNING: This task does not work for versions of Neo4j before 3.0.0'
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
65
|
desc 'Creates a db/neo4j/schema.yml file which represents the indexes / constraints in the Neo4j DB'
|
74
66
|
task dump: :environment do
|
75
|
-
|
76
|
-
require 'active_graph/migrations/schema'
|
67
|
+
require 'active_graph/migrations/schema'
|
77
68
|
|
78
|
-
|
69
|
+
schema_data = ActiveGraph::Migrations::Schema.fetch_schema_data
|
79
70
|
|
80
|
-
|
81
|
-
|
71
|
+
runner = ActiveGraph::Migrations::Runner.new
|
72
|
+
schema_data[:versions] = runner.complete_migration_versions.sort
|
82
73
|
|
83
|
-
|
84
|
-
|
74
|
+
FileUtils.mkdir_p(File.dirname(SCHEMA_YAML_PATH))
|
75
|
+
File.open(SCHEMA_YAML_PATH, 'w') { |file| file << SCHEMA_YAML_COMMENT + schema_data.to_yaml }
|
85
76
|
|
86
|
-
|
87
|
-
end
|
77
|
+
puts "Dumped updated schema file to #{SCHEMA_YAML_PATH}"
|
88
78
|
end
|
89
79
|
|
90
80
|
desc "Loads a db/neo4j/schema.yml file into the database\nOptionally removes schema elements which aren't in the schema.yml file (defaults to false)"
|
91
81
|
task :load, [:remove_missing] => :environment do |_t, args|
|
92
|
-
|
93
|
-
require 'active_graph/migrations/schema'
|
82
|
+
require 'active_graph/migrations/schema'
|
94
83
|
|
95
|
-
|
84
|
+
args.with_defaults(remove_missing: false)
|
96
85
|
|
97
|
-
|
86
|
+
schema_data = YAML.safe_load(File.read(SCHEMA_YAML_PATH), [Symbol])
|
98
87
|
|
99
|
-
|
88
|
+
ActiveGraph::Base.subscribe_to_query(&method(:puts))
|
100
89
|
|
101
|
-
|
102
|
-
ActiveGraph::Migrations::Schema.synchronize_schema_data(schema_data, args[:remove_missing])
|
103
|
-
end
|
90
|
+
ActiveGraph::Migrations::Schema.synchronize_schema_data(schema_data, args[:remove_missing])
|
104
91
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
end
|
92
|
+
ActiveGraph::Base.transaction do
|
93
|
+
runner = ActiveGraph::Migrations::Runner.new
|
94
|
+
runner.mark_versions_as_complete(schema_data[:versions]) # Run in test mode?
|
109
95
|
end
|
110
96
|
end
|
111
97
|
end
|
@@ -194,7 +180,7 @@ class #{migration_class_name} < ActiveGraph::Migrations::Base
|
|
194
180
|
drop_#{index_or_constraint} #{label.to_sym.inspect}, #{property_name.to_sym.inspect}
|
195
181
|
end
|
196
182
|
end
|
197
|
-
CONTENT
|
183
|
+
CONTENT
|
198
184
|
|
199
185
|
File.open(path, 'w') { |f| f << content }
|
200
186
|
|
@@ -1,13 +1,8 @@
|
|
1
1
|
module ActiveGraph
|
2
2
|
module Transaction
|
3
|
-
def
|
4
|
-
super
|
5
|
-
@failure = true
|
6
|
-
end
|
7
|
-
|
8
|
-
def close
|
9
|
-
success
|
3
|
+
def rollback
|
10
4
|
super
|
5
|
+
@rolled_back = true
|
11
6
|
end
|
12
7
|
|
13
8
|
def after_commit(&block)
|
@@ -15,7 +10,7 @@ module ActiveGraph
|
|
15
10
|
end
|
16
11
|
|
17
12
|
def apply_callbacks
|
18
|
-
after_commit_registry.each(&:call) unless @
|
13
|
+
after_commit_registry.each(&:call) unless @rolled_back
|
19
14
|
end
|
20
15
|
|
21
16
|
private
|
@@ -5,22 +5,19 @@ module ActiveGraph
|
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
7
|
included do
|
8
|
-
thread_mattr_accessor :explicit_session, :tx
|
8
|
+
thread_mattr_accessor :explicit_session, :tx, :last_bookmark
|
9
9
|
end
|
10
10
|
|
11
11
|
class_methods do
|
12
|
-
def session(
|
13
|
-
ActiveGraph::Base.driver.session(
|
12
|
+
def session(**session_config)
|
13
|
+
ActiveGraph::Base.driver.session(**session_config) do |session|
|
14
14
|
self.explicit_session = session
|
15
15
|
yield session
|
16
|
-
|
16
|
+
ensure
|
17
|
+
self.last_bookmark = session.last_bookmark
|
17
18
|
end
|
18
19
|
end
|
19
20
|
|
20
|
-
def transaction(**config, &block)
|
21
|
-
send_transaction(:begin_transaction, **config, &block)
|
22
|
-
end
|
23
|
-
|
24
21
|
def write_transaction(**config, &block)
|
25
22
|
send_transaction(:write_transaction, **config, &block)
|
26
23
|
end
|
@@ -29,10 +26,12 @@ module ActiveGraph
|
|
29
26
|
send_transaction(:read_transaction, **config, &block)
|
30
27
|
end
|
31
28
|
|
29
|
+
alias transaction write_transaction
|
30
|
+
|
32
31
|
private
|
33
32
|
|
34
33
|
def send_transaction(method, **config, &block)
|
35
|
-
return
|
34
|
+
return yield tx if tx&.open?
|
36
35
|
return run_transaction_work(explicit_session, method, **config, &block) if explicit_session&.open?
|
37
36
|
driver.session do |session|
|
38
37
|
run_transaction_work(session, method, **config, &block)
|
@@ -40,17 +39,19 @@ module ActiveGraph
|
|
40
39
|
end
|
41
40
|
|
42
41
|
def run_transaction_work(session, method, **config, &block)
|
42
|
+
implicit = config.delete(:implicit)
|
43
43
|
session.send(method, **config) do |tx|
|
44
44
|
self.tx = tx
|
45
|
-
|
45
|
+
block.call(tx).tap do |result|
|
46
|
+
if implicit &&
|
47
|
+
[Core::Result, ActiveGraph::Node::Query::QueryProxy, ActiveGraph::Core::Query]
|
48
|
+
.any?(&result.method(:is_a?))
|
49
|
+
result.store
|
50
|
+
end
|
51
|
+
end
|
46
52
|
end.tap { tx.apply_callbacks }
|
47
|
-
|
48
|
-
|
49
|
-
def checked_yield(tx)
|
50
|
-
yield tx
|
51
|
-
rescue StandardError => e
|
52
|
-
tx.failure
|
53
|
-
raise e
|
53
|
+
rescue ActiveGraph::Rollback
|
54
|
+
# rollbacks are silently swallowed
|
54
55
|
end
|
55
56
|
end
|
56
57
|
end
|
data/lib/active_graph/version.rb
CHANGED
data/lib/active_graph.rb
CHANGED
@@ -5,6 +5,7 @@ require 'active_graph/core'
|
|
5
5
|
require 'active_graph/core/query_ext' # From this gem
|
6
6
|
|
7
7
|
require 'active_support/core_ext/module/attribute_accessors_per_thread'
|
8
|
+
require 'active_graph/secure_random_ext'
|
8
9
|
require 'active_graph/transactions'
|
9
10
|
require 'active_graph/base'
|
10
11
|
require 'active_graph/model_schema'
|
@@ -121,3 +122,4 @@ if defined?(Rails)
|
|
121
122
|
end
|
122
123
|
|
123
124
|
Neo4j::Driver::Transaction.prepend ActiveGraph::Transaction
|
125
|
+
SecureRandom.singleton_class.prepend ActiveGraph::SecureRandomExt
|
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:
|
4
|
+
version: 11.1.0.alpha.1
|
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:
|
11
|
+
date: 2022-06-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - "!="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: 1.8.8
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: neo4j-ruby-driver
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 4.4.0.alpha.5
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 4.4.0.alpha.5
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: orm_adapter
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -136,20 +150,6 @@ dependencies:
|
|
136
150
|
- - ">="
|
137
151
|
- !ruby/object:Gem::Version
|
138
152
|
version: 0.3.0
|
139
|
-
- !ruby/object:Gem::Dependency
|
140
|
-
name: neo4j-ruby-driver
|
141
|
-
requirement: !ruby/object:Gem::Requirement
|
142
|
-
requirements:
|
143
|
-
- - "~>"
|
144
|
-
- !ruby/object:Gem::Version
|
145
|
-
version: 1.7.4
|
146
|
-
type: :development
|
147
|
-
prerelease: false
|
148
|
-
version_requirements: !ruby/object:Gem::Requirement
|
149
|
-
requirements:
|
150
|
-
- - "~>"
|
151
|
-
- !ruby/object:Gem::Version
|
152
|
-
version: 1.7.4
|
153
153
|
- !ruby/object:Gem::Dependency
|
154
154
|
name: os
|
155
155
|
requirement: !ruby/object:Gem::Requirement
|
@@ -372,6 +372,7 @@ files:
|
|
372
372
|
- lib/active_graph/relationship/types.rb
|
373
373
|
- lib/active_graph/relationship/validations.rb
|
374
374
|
- lib/active_graph/schema/operation.rb
|
375
|
+
- lib/active_graph/secure_random_ext.rb
|
375
376
|
- lib/active_graph/shared.rb
|
376
377
|
- lib/active_graph/shared/attributes.rb
|
377
378
|
- lib/active_graph/shared/callbacks.rb
|
@@ -436,14 +437,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
436
437
|
requirements:
|
437
438
|
- - ">="
|
438
439
|
- !ruby/object:Gem::Version
|
439
|
-
version: '2.
|
440
|
+
version: '2.6'
|
440
441
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
441
442
|
requirements:
|
442
|
-
- - "
|
443
|
+
- - ">"
|
443
444
|
- !ruby/object:Gem::Version
|
444
|
-
version:
|
445
|
+
version: 1.3.1
|
445
446
|
requirements: []
|
446
|
-
rubygems_version: 3.
|
447
|
+
rubygems_version: 3.3.7
|
447
448
|
signing_key:
|
448
449
|
specification_version: 4
|
449
450
|
summary: A graph database for Ruby
|