activecypher 0.8.1 → 0.9.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
  SHA256:
3
- metadata.gz: e620571f10d214866edea1ed9542b49fc0527c97e3a41d26fad6992d5c9dc900
4
- data.tar.gz: 1c79530d7aebae332ee2acaf12c25657866be8edbf3ccaaf50241308098edeba
3
+ metadata.gz: 2b70a7612e29fd973054f654ad63f28b6fe965d993073ffd39aefcdf10798326
4
+ data.tar.gz: c23ad33676db0a63bb389bb8edc597eaa4eb6f8cdcfbf44eb32e0eb4c640c1fd
5
5
  SHA512:
6
- metadata.gz: 355a7867dbce5af603a5473b061e874afbd3af77ff8f2ad1d29419e308208ff3391dfb3dedd6542dd9467d0abed5bf4f63e0940bf8d4d958352c77545558747a
7
- data.tar.gz: 6bd1446f02f78ca88d0da56da74001ffa28c1d0691619df5ba28dff319ab0e78002a41c626cf15da58749105fcd42b2bb2c4fe6b9769fc7e6cb09e57a55484f3
6
+ metadata.gz: 3688ca19c11ee45562da2a6ccd6d65be740d4ba838802ec8dc52e8453ee80e42fbd771585e31b21ab857b6acb7abc449423debbae9cd2d86a5f9207009cc847d
7
+ data.tar.gz: f86b0d54cea7d36aa2d9093d37d0a816ab4fed6485b3697bc31c9a76abda329cae4adb5c33845baccaa5e86153c36aa4996146150b224b2eb7dec927fa43a8f2
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'stringio'
4
+ require 'bigdecimal'
4
5
 
5
6
  module ActiveCypher
6
7
  module Bolt
@@ -46,6 +47,7 @@ module ActiveCypher
46
47
  NULL = 0xC0
47
48
  FALSEY = 0xC2
48
49
  TRUETHY = 0xC3
50
+ FLOAT_64 = 0xC1
49
51
 
50
52
  def initialize(io)
51
53
  @io = io
@@ -56,11 +58,13 @@ module ActiveCypher
56
58
  when String then pack_string(value)
57
59
  when Hash then pack_map(value)
58
60
  when Integer then pack_integer(value)
61
+ when Float then pack_float(value)
62
+ when BigDecimal then pack_string(value.to_s('F'))
59
63
  when TrueClass then write_marker([TRUETHY].pack('C'))
60
64
  when FalseClass then write_marker([FALSEY].pack('C'))
61
65
  when NilClass then write_marker([NULL].pack('C'))
62
66
  when Array then pack_list(value)
63
- # TODO: Add other types as needed (Float, Structure)
67
+ # TODO: Add other types maybe Postgis stuff when i'm ready for it
64
68
  else
65
69
  raise ProtocolError, "Cannot pack type: #{value.class}"
66
70
  end
@@ -134,6 +138,11 @@ module ActiveCypher
134
138
  end
135
139
  end
136
140
 
141
+ def pack_float(float)
142
+ # Pack as 64-bit double precision float in big-endian format
143
+ write_marker_and_data([FLOAT_64].pack('C'), [float].pack('G'))
144
+ end
145
+
137
146
  def write_marker(marker_bytes)
138
147
  @io.write(marker_bytes)
139
148
  end
@@ -67,6 +67,30 @@ module ActiveCypher
67
67
  "#{name} with internal_id=#{internal_db_id.inspect} not found. Perhaps it's in another castle, or just being 'graph'-ty."
68
68
  end
69
69
 
70
+ # Find the first node matching the given attributes, or return nil and question your life choices
71
+ # @param attributes [Hash] Attributes to match
72
+ # @return [Object, nil] The first matching record or nil
73
+ # Because apparently typing .where(attrs).limit(1).first was giving people RSI
74
+ def find_by(attributes = {})
75
+ return nil if attributes.blank?
76
+ where(attributes).limit(1).first
77
+ end
78
+
79
+ # Find the first node matching the given attributes or throw a tantrum
80
+ # @param attributes [Hash] Attributes to match
81
+ # @return [Object] The first matching record
82
+ # @raise [ActiveCypher::RecordNotFound] When no record is found
83
+ # For when nil isn't dramatic enough and you need your code to scream at you
84
+ def find_by!(attributes = {})
85
+ # Format attributes nicely for the error message
86
+ formatted_attrs = attributes.map { |k, v| "#{k}: #{v.inspect}" }.join(", ")
87
+
88
+ find_by(attributes) || raise(ActiveCypher::RecordNotFound,
89
+ "Couldn't find #{name} with #{formatted_attrs}. " \
90
+ "Perhaps it's hiding in another graph, or maybe it never existed. " \
91
+ "Who can say in this vast, uncaring universe of nodes and relationships?")
92
+ end
93
+
70
94
  # Instantiates and immediately saves a new record. YOLO mode.
71
95
  # @param attrs [Hash] Attributes for the new record
72
96
  # @return [Object] The new, possibly persisted record
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveCypher
4
- VERSION = '0.8.1'
4
+ VERSION = '0.9.0'
5
5
 
6
6
  def self.gem_version
7
7
  Gem::Version.new VERSION
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'cyrel/expression'
4
- require 'cyrel/expression/property_access'
5
-
6
3
  module Cyrel
7
4
  module Clause
8
5
  # Represents a SET clause in a Cypher query.
@@ -86,10 +86,7 @@ module Cyrel
86
86
 
87
87
  # Add more operators as needed (e.g., IN, STARTS WITH, CONTAINS, ENDS WITH)
88
88
  # These might be better represented as specific Comparison or FunctionCall types.
89
-
90
- # NOTE: `coerce` method moved to the Expression module itself.
91
89
  end
92
- require_relative 'alias' # Explicitly require the Alias class
93
90
 
94
91
  # Creates an aliased version of this expression.
95
92
  # @param alias_name [Symbol, String] The alias to assign.
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../expression'
4
-
5
3
  module Cyrel
6
4
  module Expression
7
5
  # Represents a CASE expression in Cypher.
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Dependencies are autoloaded by Zeitwerk based on constant usage.
4
- # Explicit requires removed.
5
-
6
3
  module Cyrel
7
4
  module Expression
8
5
  # Represents an EXISTS { pattern } predicate in Cypher.
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../expression'
4
- require_relative '../pattern' # Need Path
5
-
6
3
  module Cyrel
7
4
  module Expression
8
5
  # Represents a Pattern Comprehension in Cypher.
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'base'
4
-
5
3
  module Cyrel
6
4
  module Expression
7
5
  # Represents accessing a property on a variable (node or relationship alias).
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Subclasses are autoloaded by Zeitwerk based on constant usage.
4
- # Explicit requires removed.
5
-
6
3
  module Cyrel
7
4
  # Namespace for classes representing expressions in Cypher queries.
8
5
  # Expressions are parts of a query that evaluate to a value or condition.
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../direction'
4
-
5
3
  module Cyrel
6
4
  module Pattern
7
5
  class Relationship
data/lib/cyrel/query.rb CHANGED
@@ -1,11 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Base DSL components
4
- require 'cyrel/parameterizable'
5
- require 'cyrel/logging'
6
-
7
- # Require all clause types for DSL methods
8
-
9
3
  module Cyrel
10
4
  # Error raised when merging queries with conflicting alias definitions.
11
5
  # Because even in graphs, two things can't have the same name without drama.
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.8.1
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Abdelkader Boudih
@@ -265,7 +265,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
265
265
  - !ruby/object:Gem::Version
266
266
  version: '0'
267
267
  requirements: []
268
- rubygems_version: 3.6.7
268
+ rubygems_version: 3.6.9
269
269
  specification_version: 4
270
270
  summary: OpenCypher Adapter ala ActiveRecord
271
271
  test_files: []