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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5d9a017158867d022f2faae20f99fcbdc4196c046062e08d11bc1c77a41c48e8
4
- data.tar.gz: 42ec5aafff7b8e5e372aefdbcf414ae9eeb1640d104ebee16a1f051cb37ac94f
3
+ metadata.gz: 62237e7dafd589f3a2abe8180ada5c30b7bc12dffa5e165c428dfb4c4a25af7b
4
+ data.tar.gz: 002ef52d6ad7e0f6735db23c37b033dc24df6af2e0ddd116d593ed88f21f00a1
5
5
  SHA512:
6
- metadata.gz: 6274d56abf4d330f8e29d5ebba5f788d44355eb079df9730a380ad0433899bccfbd250d89cd0d88cfe67e7e52bf8ff8e981cc34bbc668faf639d66affe724233
7
- data.tar.gz: 0b7418a39e465ff94705b3cccc72ff41bc66a1dfe25791dbbcca07e331e6694348fefdb9bfb82139d3d90d582b90e6b48ea8defa491dd6b25dc18f233015d4ec
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
@@ -2,7 +2,7 @@ source 'http://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
- #gem "neo4j-#{ENV['driver'] == 'java' ? 'java' : 'ruby'}-driver", path: '../neo4j-ruby-driver'
5
+ # gem 'neo4j-ruby-driver', path: '../neo4j-ruby-driver'
6
6
 
7
7
  gem 'listen', '< 3.1'
8
8
 
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.0 |
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, 3.5 | No | No | No | Yes | Yes |
57
- | 4.0 | No | No | No | No | Yes |
58
- | 4.1 | No | No | No | No | No |
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.5'
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')
@@ -30,7 +30,7 @@ module ActiveGraph
30
30
  end
31
31
 
32
32
  def query(*args)
33
- transaction do
33
+ transaction(implicit: true) do
34
34
  super(*args)
35
35
  end
36
36
  end
@@ -114,8 +114,9 @@ module ActiveGraph
114
114
  end
115
115
 
116
116
  def drop_constraints
117
- ActiveGraph::Base.transaction do |tx|
118
- tx.run('CALL db.constraints').each do |record|
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
- queries(options) { append(*args) }[0]
21
+ query_run(QueryBuilder.query(*args), options)
22
22
  end
23
23
 
24
- def queries(options = {}, &block)
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
- queries.each do |query|
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 query_set(queries, options = {})
42
- setup_queries!(queries, skip_instrumentation: options[:skip_instrumentation])
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
- queries.map do |query|
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 initialize
9
- @queries = []
10
- end
11
-
12
- def append(*args)
13
- query = case args.map(&:class)
14
- when [String], [String, Hash]
15
- Query.new(args[0], args[1] || {})
16
- when [::ActiveGraph::Core::Query]
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? ? wrapping_each(&block) : super
15
+ store if wrap? # TODO: why? This is preventing streaming
16
+ @records&.each(&block) || super
12
17
  end
13
18
 
14
- private
15
-
16
- def wrapping_each(&block)
17
- if @records
18
- @records.each(&block)
19
- else
20
- @records = []
21
- method(:each).super_method.call do |record|
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
- result = query('CALL dbms.components()', {}, skip_instrumentation: true)
6
-
7
- # BTW: community / enterprise could be retrieved via `result.first.edition`
8
- result.first[:versions][0]
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
- result = query('CALL db.indexes()', {}, skip_instrumentation: true)
13
-
14
- result.map do |row|
15
- { type: row[:type].to_sym, label: label(result, row), properties: properties(row), state: row[:state].to_sym }
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
- result = query('CALL db.indexes()', {}, skip_instrumentation: true)
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
- result.select(&method(v4?(result) ? :v4_filter : :v3_filter)).map do |row|
23
- { type: :uniqueness, label: label(result, row), properties: properties(row) }
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(result, row)
38
- if v34?(result)
45
+ def label(keys, row)
46
+ if v34?(keys)
39
47
  row[:label]
40
48
  else
41
- (v4?(result) ? row[:labelsOrTypes] : row[:tokenNames]).first
49
+ (v4?(keys) ? row[:labelsOrTypes] : row[:tokenNames]).first
42
50
  end.to_sym
43
51
  end
44
52
 
45
- def v4?(result)
53
+ def v4?(keys)
46
54
  return @v4 unless @v4.nil?
47
- @v4 = result.keys.include?(:labelsOrTypes)
55
+ @v4 = keys.include?(:labelsOrTypes)
48
56
  end
49
57
 
50
- def v34?(result)
58
+ def v34?(keys)
51
59
  return @v34 unless @v34.nil?
52
- @v34 = result.keys.include?(:label)
60
+ @v34 = keys.include?(:label)
53
61
  end
54
62
 
55
63
  def properties(row)
@@ -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::StatementResult.prepend ActiveGraph::Core::Result
13
+ Neo4j::Driver::Result.prepend ActiveGraph::Core::Result
14
14
  Neo4j::Driver::Record.prepend ActiveGraph::Core::Record
@@ -54,4 +54,6 @@ module ActiveGraph
54
54
  defined?(Rails)
55
55
  end
56
56
  end
57
+
58
+ class Rollback < Error; end
57
59
  end
@@ -57,9 +57,12 @@ module ActiveGraph
57
57
  end
58
58
 
59
59
  def handle_migration_error!(e)
60
- fail e unless e.message =~ /Cannot perform data updates in a transaction that has performed schema updates./
61
- fail MigrationError,
62
- "#{e.message}. Please add `disable_transactions!` in your migration file."
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
- 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
- ActiveGraph::Base.queries do
15
- queries.each { |query| append query }
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
- result = ActiveGraph::Base.query('CALL db.indexes()')
27
- if result.keys.include?(:description)
28
- v3_indexes(result)
29
- else
30
- v4_indexes(result)
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.relationship_class_name == relationship.class.name ||
257
- (assoc.relationship_type == relationship.type.to_sym && assoc.target_class == target_class && assoc.direction == direction)
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
 
@@ -58,6 +58,7 @@ module ActiveGraph
58
58
  def process_string(str)
59
59
  head, rest = str.split('.', 2)
60
60
  k, length = head.split('*', -2)
61
+ length = {max: length} if length
61
62
  add_nested(k.to_sym, rest, length)
62
63
  end
63
64
 
@@ -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
- if rel_length
161
- rel_name = nil
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
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveGraph
4
+ module SecureRandomExt
5
+ def hex(n = nil)
6
+ super.force_encoding(Encoding::UTF_8)
7
+ end
8
+
9
+ def uuid
10
+ super.force_encoding(Encoding::UTF_8)
11
+ end
12
+ end
13
+ end
@@ -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(&:failure) if result == false
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.failure unless saved
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, Neo4j::Driver::Types::Bytes, ActiveSupport::Duration, Neo4j::Driver::Types::Point,
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
- check_neo4j_version_3 do
76
- require 'active_graph/migrations/schema'
67
+ require 'active_graph/migrations/schema'
77
68
 
78
- schema_data = ActiveGraph::Migrations::Schema.fetch_schema_data
69
+ schema_data = ActiveGraph::Migrations::Schema.fetch_schema_data
79
70
 
80
- runner = ActiveGraph::Migrations::Runner.new
81
- schema_data[:versions] = runner.complete_migration_versions.sort
71
+ runner = ActiveGraph::Migrations::Runner.new
72
+ schema_data[:versions] = runner.complete_migration_versions.sort
82
73
 
83
- FileUtils.mkdir_p(File.dirname(SCHEMA_YAML_PATH))
84
- File.open(SCHEMA_YAML_PATH, 'w') { |file| file << SCHEMA_YAML_COMMENT + schema_data.to_yaml }
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
- puts "Dumped updated schema file to #{SCHEMA_YAML_PATH}"
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
- check_neo4j_version_3 do
93
- require 'active_graph/migrations/schema'
82
+ require 'active_graph/migrations/schema'
94
83
 
95
- args.with_defaults(remove_missing: false)
84
+ args.with_defaults(remove_missing: false)
96
85
 
97
- schema_data = YAML.safe_load(File.read(SCHEMA_YAML_PATH), [Symbol])
86
+ schema_data = YAML.safe_load(File.read(SCHEMA_YAML_PATH), [Symbol])
98
87
 
99
- ActiveGraph::Base.subscribe_to_query(&method(:puts))
88
+ ActiveGraph::Base.subscribe_to_query(&method(:puts))
100
89
 
101
- ActiveGraph::Base.transaction do
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
- ActiveGraph::Base.transaction do
106
- runner = ActiveGraph::Migrations::Runner.new
107
- runner.mark_versions_as_complete(schema_data[:versions]) # Run in test mode?
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 failure
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 @failure
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(*args)
13
- ActiveGraph::Base.driver.session(*args) do |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
- session.last_bookmark
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 checked_yield(tx, &block) if tx&.open?
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
- checked_yield(tx, &block)
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
- end
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
@@ -1,3 +1,3 @@
1
1
  module ActiveGraph
2
- VERSION = '10.1.0'
2
+ VERSION = '11.1.0.alpha.1'
3
3
  end
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: 10.1.0
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: 2021-02-06 00:00:00.000000000 Z
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.5'
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: '0'
445
+ version: 1.3.1
445
446
  requirements: []
446
- rubygems_version: 3.2.3
447
+ rubygems_version: 3.3.7
447
448
  signing_key:
448
449
  specification_version: 4
449
450
  summary: A graph database for Ruby