activecypher 0.11.0 → 0.11.1

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
  SHA256:
3
- metadata.gz: 2396c4b661d5d743f6c35c7921d020f096531f543c7df9b99e05bddf84c9a2db
4
- data.tar.gz: 51e407abc0ac00aaa315fd8acdf489fad8a8d8ae3a46702df4b97c8347ea3fbd
3
+ metadata.gz: a39f60243be9073a1c3e2f05e1239239de9412d95184a321d22c4f582b0cdbdb
4
+ data.tar.gz: f125c98717432f24b3e0e28e4066f962cc2cb46bbab556bda52a44c3f4f12e7c
5
5
  SHA512:
6
- metadata.gz: 210b7c45581497c2ab69a3609e452dba832c0b15ccd3dbf1ee81740f7e4a4c693c537745ea9de13b3904f4c2c5c8386fecfd3fa45eab7e98ce2e7c8976b85cf6
7
- data.tar.gz: 29df9c560d01ec8ce6e8c7eee1e977d6a1b61dc532c7af929b3da101fbf9f3440afdd4332a9b7cc2c2f4af1ab420e51bcc21f55841e9a1b57f94120371459610
6
+ metadata.gz: 3bea961b864932446e0c667c7f88c9a428204f62089696b65d32dc62c4297e10e7d86e1f2ce67db8eb32e3a771944d882840b5d416345eed3296a3b23dec1d09
7
+ data.tar.gz: 1803663082f2fa06c7af69af355d0bd05ad78901c217c8b5f2aa2486b3adc009a6784d11b09731b1bd88d0b533e12420c13b11254b4b0852de5636b1e0d530f3
@@ -34,7 +34,6 @@ module ActiveCypher
34
34
  include Model::Persistence
35
35
  include Model::Destruction
36
36
  include Model::Countable
37
- include Model::Inspectable
38
37
 
39
38
  class << self
40
39
  # Attempts to retrieve a connection from the handler.
@@ -61,6 +60,24 @@ module ActiveCypher
61
60
  end
62
61
  end
63
62
 
63
+ # Custom object inspection method for pretty-printing a compact,
64
+ # single-line summary of the object. Output examples:
65
+ #
66
+ # #<UserNode id="26" name="Alice" age=34> => persisted object
67
+ # #<UserNode (new) name="Bob"> => object not yet saved
68
+ #
69
+ def inspect
70
+ # Put 'internal_id' first like it's the main character (even if it's nil)
71
+ ordered = attributes.dup
72
+ ordered = ordered.slice('internal_id').merge(ordered.except('internal_id'))
73
+
74
+ # Turn each attr into "key: value" because we humans fear raw hashes
75
+ parts = ordered.map { |k, v| "#{k}: #{v.inspect}" }
76
+
77
+ # Wrap it all up in a fake-sane object string, so you can pretend your data is organized.
78
+ "#<#{self.class} #{parts.join(', ')}>"
79
+ end
80
+
64
81
  # Because Rails needs to feel included, too.
65
82
  ActiveSupport.run_load_hooks(:active_cypher, self)
66
83
  end
@@ -133,7 +133,7 @@ module ActiveCypher
133
133
  #
134
134
  # @note The digital equivalent of ghosting.
135
135
  def close
136
- @socket&.close if connected?
136
+ @socket.close if connected?
137
137
  rescue IOError
138
138
  ensure
139
139
  @socket = nil
@@ -47,11 +47,7 @@ module ActiveCypher
47
47
  # Check if connection is viable before using it
48
48
  unless conn.viable?
49
49
  # Create a fresh connection, because hope springs eternal
50
- begin
51
- conn.close
52
- rescue StandardError
53
- nil
54
- end
50
+ conn.close
55
51
  conn = build_connection
56
52
  end
57
53
 
@@ -64,11 +60,7 @@ module ActiveCypher
64
60
  # Check if connection is viable before using it
65
61
  unless conn.viable?
66
62
  # Create a fresh connection, because why not
67
- begin
68
- conn.close
69
- rescue StandardError
70
- nil
71
- end
63
+ conn.close
72
64
  conn = build_connection
73
65
  end
74
66
 
@@ -88,8 +80,6 @@ module ActiveCypher
88
80
  def verify_connectivity
89
81
  with_session { |s| s.run('RETURN 1') }
90
82
  true
91
- rescue StandardError
92
- false
93
83
  end
94
84
 
95
85
  # Closes the connection pool. Because sometimes you just need to let go.
@@ -119,11 +109,7 @@ module ActiveCypher
119
109
  begin
120
110
  connection.connect
121
111
  rescue StandardError => e
122
- begin
123
- connection.close
124
- rescue StandardError
125
- nil
126
- end
112
+ connection.close
127
113
  raise e
128
114
  end
129
115
 
@@ -7,6 +7,7 @@ module ActiveCypher
7
7
  # It maintains a connection to the database server and allows running queries.
8
8
  class Session
9
9
  include Instrumentation
10
+
10
11
  attr_reader :connection, :database
11
12
 
12
13
  def initialize(connection, database: nil)
@@ -119,15 +120,15 @@ module ActiveCypher
119
120
  # @param metadata [Hash] Transaction metadata to send to the server.
120
121
  # @yield [tx] The transaction to use for queries.
121
122
  # @return The result of the block.
122
- def run_transaction(mode = :write, db: nil, timeout: nil, metadata: nil, &block)
123
+ def run_transaction(mode = :write, db: nil, timeout: nil, metadata: nil, &)
123
124
  if Async::Task.current?
124
125
  # Already in an async context, just run the block.
125
126
  # The block will run asynchronously within the current task.
126
- _execute_transaction_block(mode, db, timeout, metadata, &block)
127
+ _execute_transaction_block(mode, db, timeout, metadata, &)
127
128
  else
128
129
  # Not in an async context, so we need to create one and wait for it to complete.
129
130
  Async do
130
- _execute_transaction_block(mode, db, timeout, metadata, &block)
131
+ _execute_transaction_block(mode, db, timeout, metadata, &)
131
132
  end.wait
132
133
  end
133
134
  end
@@ -141,12 +142,12 @@ module ActiveCypher
141
142
  # @param metadata [Hash] Transaction metadata to send to the server.
142
143
  # @yield [tx] The transaction to use for queries.
143
144
  # @return [Async::Task] A task that will complete with the result of the block.
144
- def async_run_transaction(mode = :write, db: nil, timeout: nil, metadata: nil, &block)
145
+ def async_run_transaction(mode = :write, db: nil, timeout: nil, metadata: nil, &)
145
146
  # Ensure we are in an async task, otherwise the behavior is undefined.
146
147
  raise 'Cannot run an async transaction outside of an Async task' unless Async::Task.current?
147
148
 
148
149
  Async do
149
- _execute_transaction_block(mode, db, timeout, metadata, &block)
150
+ _execute_transaction_block(mode, db, timeout, metadata, &)
150
151
  end
151
152
  end
152
153
 
@@ -158,12 +159,12 @@ module ActiveCypher
158
159
  run_transaction(:read, db: db, timeout: timeout, metadata: metadata, &)
159
160
  end
160
161
 
161
- def async_write_transaction(db: nil, timeout: nil, metadata: nil, &block)
162
- async_run_transaction(:write, db: db, timeout: timeout, metadata: metadata, &block)
162
+ def async_write_transaction(db: nil, timeout: nil, metadata: nil, &)
163
+ async_run_transaction(:write, db: db, timeout: timeout, metadata: metadata, &)
163
164
  end
164
165
 
165
- def async_read_transaction(db: nil, timeout: nil, metadata: nil, &block)
166
- async_run_transaction(:read, db: db, timeout: timeout, metadata: metadata, &block)
166
+ def async_read_transaction(db: nil, timeout: nil, metadata: nil, &)
167
+ async_run_transaction(:read, db: db, timeout: timeout, metadata: metadata, &)
167
168
  end
168
169
 
169
170
  # Close the session and any active transaction.
@@ -5,6 +5,7 @@ module ActiveCypher
5
5
  # Manages transaction state (BEGIN/COMMIT/ROLLBACK) and runs queries within a transaction.
6
6
  class Transaction
7
7
  include Instrumentation
8
+
8
9
  attr_reader :bookmarks, :metadata, :connection
9
10
 
10
11
  # Initializes a new Transaction instance.
@@ -147,11 +148,7 @@ module ActiveCypher
147
148
  rescue ConnectionError
148
149
  @state = :failed
149
150
  # Mark transaction as completed in the session
150
- begin
151
- @session.complete_transaction(self)
152
- rescue StandardError
153
- nil
154
- end
151
+ @session.complete_transaction(self)
155
152
  raise
156
153
  end
157
154
 
@@ -184,11 +181,7 @@ module ActiveCypher
184
181
  ensure
185
182
  # Always mark as rolled back and complete the transaction
186
183
  @state = :rolled_back
187
- begin
188
- @session.complete_transaction(self)
189
- rescue StandardError
190
- nil
191
- end
184
+ @session.complete_transaction(self)
192
185
  end
193
186
  end
194
187
 
@@ -57,34 +57,6 @@ module ActiveCypher
57
57
  raise NotImplementedError, "#{self.class} must implement #hydrate_record"
58
58
  end
59
59
 
60
- # Get current adapter type for ID handling
61
- # Helper for generating ID-related Cypher functions that are database-specific
62
- module CypherFunction
63
- # Generate ID equality clause with the ID value embedded in the query for Memgraph
64
- def self.id_equals(var, id_value, adapter)
65
- func = id_function(adapter)
66
- "#{func}(#{var}) = #{id_value}"
67
- end
68
-
69
- # Generate ID equality clause using a parameterized ID value for Neo4j
70
- def self.id_equals_param(var, param_name, adapter)
71
- func = id_function(adapter)
72
- "#{func}(#{var}) = $#{param_name}"
73
- end
74
-
75
- # Generate a node variable with ID predicate
76
- def self.node_with_id(node_var, id_value, adapter)
77
- func = id_function(adapter)
78
- "#{func}(#{node_var}) = #{id_value}"
79
- end
80
-
81
- # Return ID expression
82
- def self.return_id(var, as_name, adapter)
83
- func = id_function(adapter)
84
- "#{func}(#{var}) AS #{as_name}"
85
- end
86
- end
87
-
88
60
  # Turns rows into symbols, because Rubyists fear strings.
89
61
  # @param rows [Array<Hash>] The rows to process
90
62
  # @return [Array<Hash>] The processed rows
@@ -10,6 +10,7 @@ module ActiveCypher
10
10
  # It's like ActiveRecord::ConnectionAdapter, but for weirdos like me who use graph databases.
11
11
  class AbstractBoltAdapter < AbstractAdapter
12
12
  include Instrumentation
13
+
13
14
  attr_reader :connection
14
15
 
15
16
  # Returns the raw Bolt connection object
@@ -71,7 +72,7 @@ module ActiveCypher
71
72
  # Clean disconnection. Resets the internal state.
72
73
  def disconnect
73
74
  instrument_connection(:disconnect) do
74
- @connection&.close
75
+ @connection.close if @connection
75
76
  @connection = nil
76
77
  true
77
78
  end
@@ -11,8 +11,6 @@ module ActiveCypher
11
11
  def schema_catalog
12
12
  rows = run('SHOW SCHEMA')
13
13
  parse_schema(rows)
14
- rescue StandardError
15
- introspect_fallback
16
14
  end
17
15
 
18
16
  # Use id() for Memgraph instead of elementId()
@@ -198,6 +196,7 @@ module ActiveCypher
198
196
 
199
197
  module Persistence
200
198
  include PersistenceMethods
199
+
201
200
  module_function :create_record, :update_record, :destroy_record
202
201
  end
203
202
 
@@ -33,8 +33,6 @@ module ActiveCypher
33
33
 
34
34
  Schema::Catalog.new(indexes: idx_defs, constraints: con_defs,
35
35
  node_types: [], edge_types: [])
36
- rescue StandardError
37
- Schema::Catalog.new(indexes: [], constraints: [], node_types: [], edge_types: [])
38
36
  end
39
37
 
40
38
  # Use elementId() for Neo4j
@@ -156,6 +154,7 @@ module ActiveCypher
156
154
 
157
155
  module Persistence
158
156
  include PersistenceMethods
157
+
159
158
  module_function :create_record, :update_record, :destroy_record
160
159
  end
161
160
 
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'concurrent/atomic/atomic_reference'
4
3
  require 'timeout'
5
4
 
6
5
  module ActiveCypher
@@ -24,29 +23,27 @@ module ActiveCypher
24
23
 
25
24
  # Merge the resolved config with any additional options
26
25
  @spec = resolved_config.merge(@spec.except(:url))
27
-
28
26
  end
29
27
 
30
- @conn_ref = Concurrent::AtomicReference.new # holds the adapter instance
28
+ @conn_ref = nil # holds the adapter instance
31
29
  @creation_mutex = Mutex.new # prevents multiple threads from creating connections simultaneously
32
- @retry_count = Concurrent::AtomicReference.new(0)
33
30
  end
34
31
 
35
- # Returns a live adapter, initialising it once in a thread‑safe way.
32
+ # Returns a live adapter, initializing it once in a thread‑safe way.
36
33
  def connection
37
- # Fast path —already connected and alive
38
- conn = @conn_ref.value
34
+ # Fast path — already connected and alive
35
+ conn = @conn_ref
39
36
  return conn if conn&.active?
40
37
 
41
38
  # Use mutex for the slow path to prevent thundering herd
42
39
  @creation_mutex.synchronize do
43
40
  # Check again inside the mutex in case another thread created it
44
- conn = @conn_ref.value
41
+ conn = @conn_ref
45
42
  return conn if conn&.active?
46
43
 
47
44
  # Create a new connection
48
45
  new_conn = build_connection
49
- @conn_ref.set(new_conn)
46
+ @conn_ref = new_conn
50
47
  return new_conn
51
48
  end
52
49
  end
@@ -54,12 +51,12 @@ module ActiveCypher
54
51
 
55
52
  # Check if the pool has a persistent connection issue
56
53
  def troubled?
57
- @retry_count.value >= @spec[:max_retries]
54
+ @retry_count >= @spec[:max_retries]
58
55
  end
59
56
 
60
57
  # Explicitly close and reset the connection
61
58
  def disconnect
62
- conn = @conn_ref.value
59
+ conn = @conn_ref
63
60
  return unless conn
64
61
 
65
62
  begin
@@ -68,7 +65,7 @@ module ActiveCypher
68
65
  # Log but don't raise to ensure cleanup continues
69
66
  puts "Warning: Error disconnecting: #{e.message}" if ENV['DEBUG']
70
67
  ensure
71
- @conn_ref.set(nil)
68
+ @conn_ref = nil
72
69
  end
73
70
  end
74
71
 
@@ -91,8 +88,8 @@ module ActiveCypher
91
88
  rescue Timeout::Error
92
89
  begin
93
90
  adapter.disconnect
94
- rescue StandardError
95
- nil
91
+ rescue StandardError => e
92
+ puts "Warning: Error disconnecting during timeout cleanup: #{e.message}" if ENV['DEBUG']
96
93
  end
97
94
  raise ConnectionError, "Connection timed out after #{@spec[:pool_timeout]} seconds"
98
95
  end
@@ -32,11 +32,7 @@ module ActiveCypher
32
32
 
33
33
  # 5. Gather unique connections for all model classes referenced in this profile
34
34
  model_classes = dsl_context.nodes.map { |node| node[:model_class] }.uniq
35
- connections = model_classes.map do |klass|
36
- klass.connection
37
- rescue StandardError
38
- nil
39
- end.compact.uniq
35
+ connections = model_classes.map(&:connection).compact.uniq
40
36
 
41
37
  # 6. Wipe all nodes in each relevant connection
42
38
  connections.each do |conn|
@@ -78,11 +74,7 @@ module ActiveCypher
78
74
  end
79
75
 
80
76
  # Gather unique connections from all model classes
81
- connections = model_classes.map do |klass|
82
- klass.connection
83
- rescue StandardError
84
- nil
85
- end.compact.uniq
77
+ connections = model_classes.map(&:connection).compact.uniq
86
78
 
87
79
  # Wipe all nodes in each connection
88
80
  connections.each do |conn|
@@ -104,17 +96,13 @@ module ActiveCypher
104
96
  next unless klass < ActiveCypher::Base
105
97
  next if klass.respond_to?(:abstract_class?) && klass.abstract_class?
106
98
 
107
- begin
108
- conn = klass.connection
109
- # Store connection details for comparison
110
- model_connections[klass] = {
111
- adapter: conn.class.name,
112
- config: conn.instance_variable_get(:@config),
113
- object_id: conn.object_id
114
- }
115
- rescue StandardError
116
- # Skip if can't get connection
117
- end
99
+ conn = klass.connection
100
+ # Store connection details for comparison
101
+ model_connections[klass] = {
102
+ adapter: conn.class.name,
103
+ config: conn.instance_variable_get(:@config),
104
+ object_id: conn.object_id
105
+ }
118
106
  end
119
107
 
120
108
  relationships.each do |rel|
@@ -132,7 +132,7 @@ module ActiveCypher
132
132
  # @param key [String, Symbol] The key to check
133
133
  # @return [Boolean] True if the key contains sensitive information
134
134
  def sensitive_key?(key)
135
- return true if key.to_s.match?(/(^|[\-_])(?:password|token|secret|credential|key)($|[\-_])/i)
135
+ return true if key.to_s.match?(/(^|[-_])(?:password|token|secret|credential|key)($|[-_])/i)
136
136
 
137
137
  # Check against Rails filter parameters if available
138
138
  if defined?(Rails) && Rails.application
@@ -14,11 +14,7 @@ module ActiveCypher
14
14
  self.backend ||= begin
15
15
  base = Logger.new($stdout)
16
16
  base.level = ENV.fetch('AC_LOG_LEVEL', 'info').upcase
17
- .then do |lvl|
18
- Logger.const_get(lvl)
19
- rescue StandardError
20
- Logger::INFO
21
- end
17
+ .then { |lvl| Logger.const_get(lvl) }
22
18
  ActiveSupport::TaggedLogging.new(base).tap { |l| l.tagged! 'ActiveCypher' }
23
19
  end
24
20
  end
@@ -64,8 +64,6 @@ module ActiveCypher
64
64
  def existing_versions
65
65
  @connection.execute_cypher('MATCH (m:SchemaMigration) RETURN m.version AS version')
66
66
  .map { |r| r[:version].to_s }
67
- rescue StandardError
68
- []
69
67
  end
70
68
 
71
69
  def ensure_schema_migration_constraint
@@ -23,7 +23,8 @@ module ActiveCypher
23
23
 
24
24
  # Returns the adapter class being used by this model
25
25
  def adapter_class
26
- connection&.class
26
+ conn = connection
27
+ conn&.class
27
28
  end
28
29
 
29
30
  # Always dynamically fetch the connection for the current db_key
@@ -73,11 +73,7 @@ module ActiveCypher
73
73
 
74
74
  return @connection if defined?(@connection) && @connection
75
75
 
76
- begin
77
- from_class.constantize.connection
78
- rescue StandardError
79
- nil
80
- end
76
+ from_class.constantize.connection
81
77
  end
82
78
 
83
79
  # --------------------------------------------------------------
@@ -301,9 +297,14 @@ module ActiveCypher
301
297
  _run(:update) { update_relationship }
302
298
  end
303
299
  end
304
- rescue StandardError => e
305
- log_error "Failed to save #{self.class}: #{e.class} #{e.message}"
306
- false
300
+ rescue ActiveCypher::RecordNotSaved, RuntimeError => e
301
+ # Only catch specific validation errors, let other errors propagate
302
+ if e.message.include?('must be persisted') || e.message.include?('creation returned no id')
303
+ log_error "Failed to save #{self.class}: #{e.message}"
304
+ false
305
+ else
306
+ raise
307
+ end
307
308
  end
308
309
 
309
310
  # Bang version of save - raises exception if save fails
@@ -396,9 +397,6 @@ module ActiveCypher
396
397
  @new_record = false
397
398
  changes_applied
398
399
  true
399
- rescue StandardError => e
400
- log_error "Failed to save #{self.class}: #{e.class} – #{e.message}"
401
- false
402
400
  end
403
401
 
404
402
  def update_relationship
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveCypher
4
- VERSION = '0.11.0'
4
+ VERSION = '0.11.1'
5
5
 
6
6
  def self.gem_version
7
7
  Gem::Version.new VERSION
@@ -9,20 +9,14 @@ module Cyrel
9
9
 
10
10
  def initialize(ast_node)
11
11
  @ast_node = ast_node
12
- @ast_node_hash = ast_node.hash
13
12
  super()
14
13
  end
15
14
 
16
15
  def render(query)
17
- # Use a simple cache key based on AST node structure
18
- cache_key = [@ast_node_hash, @ast_node.class.name].join(':')
19
-
20
- SimpleCache.instance.fetch(cache_key) do
21
- # Create a compiler that delegates parameter registration to the query
22
- compiler = QueryIntegratedCompiler.new(query)
23
- compiler.compile(ast_node)
24
- compiler.output.string
25
- end
16
+ # Create a compiler that delegates parameter registration to the query
17
+ compiler = QueryIntegratedCompiler.new(query)
18
+ compiler.compile(ast_node)
19
+ compiler.output.string
26
20
  end
27
21
 
28
22
  # Ruby 3.0+ pattern matching support
@@ -11,13 +11,8 @@ module Cyrel
11
11
 
12
12
  def initialize
13
13
  @output = StringIO.new
14
- if defined?(Concurrent)
15
- @parameters = Concurrent::Hash.new
16
- @param_counter = Concurrent::AtomicFixnum.new(0)
17
- else
18
- @parameters = {}
19
- @param_counter = 0
20
- end
14
+ @parameters = {}
15
+ @param_counter = 0
21
16
  @first_clause = true
22
17
  @loop_variables = Set.new # Track loop variables that shouldn't be parameterized
23
18
  end
@@ -573,17 +568,9 @@ module Cyrel
573
568
  existing_key = @parameters.key(value)
574
569
  return existing_key if existing_key
575
570
 
576
- if defined?(Concurrent) && @parameters.is_a?(Concurrent::Hash)
577
- # Thread-safe parameter registration
578
-
579
- counter = @param_counter.increment
580
- key = :"p#{counter}"
581
- else
582
- # Non-concurrent version
583
-
584
- @param_counter += 1
585
- key = :"p#{@param_counter}"
586
- end
571
+ # Parameter registration
572
+ @param_counter += 1
573
+ key = :"p#{@param_counter}"
587
574
  @parameters[key] = value
588
575
  key
589
576
  end
data/lib/cyrel/logging.rb CHANGED
@@ -15,8 +15,6 @@ module Cyrel
15
15
 
16
16
  def resolve_log_level(log_level_str)
17
17
  Logger.const_get(log_level_str.upcase)
18
- rescue StandardError
19
- Logger::UNKNOWN
20
18
  end
21
19
 
22
20
  def logger
data/lib/cyrel/query.rb CHANGED
@@ -15,6 +15,7 @@ module Cyrel
15
15
  class Query
16
16
  include Parameterizable
17
17
  include Logging
18
+
18
19
  attr_reader :parameters, :clauses # Expose clauses for merge logic
19
20
 
20
21
  def initialize
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activecypher
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.0
4
+ version: 0.11.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Abdelkader Boudih
@@ -154,7 +154,6 @@ files:
154
154
  - lib/active_cypher/model/core.rb
155
155
  - lib/active_cypher/model/countable.rb
156
156
  - lib/active_cypher/model/destruction.rb
157
- - lib/active_cypher/model/inspectable.rb
158
157
  - lib/active_cypher/model/labelling.rb
159
158
  - lib/active_cypher/model/persistence.rb
160
159
  - lib/active_cypher/model/querying.rb
@@ -192,7 +191,6 @@ files:
192
191
  - lib/cyrel/ast/remove_node.rb
193
192
  - lib/cyrel/ast/return_node.rb
194
193
  - lib/cyrel/ast/set_node.rb
195
- - lib/cyrel/ast/simple_cache.rb
196
194
  - lib/cyrel/ast/skip_node.rb
197
195
  - lib/cyrel/ast/union_node.rb
198
196
  - lib/cyrel/ast/unwind_node.rb
@@ -265,7 +263,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
265
263
  - !ruby/object:Gem::Version
266
264
  version: '0'
267
265
  requirements: []
268
- rubygems_version: 3.6.7
266
+ rubygems_version: 3.6.9
269
267
  specification_version: 4
270
268
  summary: OpenCypher Adapter ala ActiveRecord
271
269
  test_files: []
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveCypher
4
- module Model
5
- # @!parse
6
- # # Adds a custom inspect method for pretty-printing a compact, single-line summary of the object.
7
- # # Because nothing says "debuggable" like a string that pretends your object is more interesting than it is.
8
- module Inspectable
9
- # Custom object inspection method for pretty-printing a compact,
10
- # single-line summary of the object. Output examples:
11
- #
12
- # #<UserNode id="26" name="Alice" age=34> => persisted object
13
- # #<UserNode (new) name="Bob"> => object not yet saved
14
- #
15
- def inspect
16
- # Put 'internal_id' first like it's the main character (even if it's nil)
17
- ordered = attributes.dup
18
- ordered = ordered.slice('internal_id').merge(ordered.except('internal_id'))
19
-
20
- # Turn each attr into "key: value" because we humans fear raw hashes
21
- parts = ordered.map { |k, v| "#{k}: #{v.inspect}" }
22
-
23
- # Wrap it all up in a fake-sane object string, so you can pretend your data is organized.
24
- "#<#{self.class} #{parts.join(', ')}>"
25
- end
26
- end
27
- end
28
- end
@@ -1,50 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'singleton'
4
-
5
- module Cyrel
6
- module AST
7
- # Simple thread-safe compilation cache
8
- # Because compiling the same query twice is like watching reruns
9
- class SimpleCache
10
- include Singleton
11
-
12
- def initialize
13
- @cache = {}
14
- @mutex = Mutex.new
15
- @max_size = 1000
16
- end
17
-
18
- def fetch(key)
19
- @mutex.synchronize do
20
- if @cache.key?(key)
21
- @cache[key]
22
- elsif block_given?
23
- value = yield
24
- store(key, value)
25
- value
26
- end
27
- end
28
- end
29
-
30
- def clear!
31
- @mutex.synchronize { @cache.clear }
32
- end
33
-
34
- def size
35
- @mutex.synchronize { @cache.size }
36
- end
37
-
38
- private
39
-
40
- def store(key, value)
41
- # Simple LRU: remove oldest entries when cache is full
42
- if @cache.size >= @max_size
43
- # Remove half of the oldest entries
44
- (@max_size / 2).times { @cache.shift }
45
- end
46
- @cache[key] = value
47
- end
48
- end
49
- end
50
- end