lora-ruby 0.2.0-x86_64-linux
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 +7 -0
- data/LICENSE +87 -0
- data/README.md +190 -0
- data/lib/lora_ruby/3.1/lora_ruby.so +0 -0
- data/lib/lora_ruby/3.2/lora_ruby.so +0 -0
- data/lib/lora_ruby/3.3/lora_ruby.so +0 -0
- data/lib/lora_ruby/types.rb +140 -0
- data/lib/lora_ruby/version.rb +14 -0
- data/lib/lora_ruby.rb +46 -0
- metadata +102 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: a1070b9b3c1c0f6417eb4fec39a875ab9a966cf7dc9679608e79817129df050e
|
|
4
|
+
data.tar.gz: ab88ef302defb70eca748d401d558f9136f08792addb462863d2cfe42a7da4bb
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 2e30841ef82bea511be9d40974175638995a2981117926b969bc09565c957044f4a344b635393c4f3998810affa889c9323c5761ad0efa4cb7eaa5202eac1f1d
|
|
7
|
+
data.tar.gz: 3fd3df27863a1c38432dcc75215248dac2dce75c65e3b6b57b81b08de33c54ecf7a53804c5bfb5c0a7ccf64a1fd36b22c7652ea6296994afd0c7a912f1121b30
|
data/LICENSE
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
Business Source License 1.1
|
|
2
|
+
|
|
3
|
+
Parameters
|
|
4
|
+
|
|
5
|
+
Licensor: LoraDB, Inc.
|
|
6
|
+
Licensed Work: LoraDB
|
|
7
|
+
Change Date: 2029-04-19
|
|
8
|
+
Change License: Apache License, Version 2.0
|
|
9
|
+
|
|
10
|
+
Additional Use Grant: You may use, copy, modify, create derivative works of,
|
|
11
|
+
distribute, and make production use of the Licensed Work
|
|
12
|
+
for internal business purposes and non-production
|
|
13
|
+
purposes, provided that you do not use the Licensed Work
|
|
14
|
+
to offer, operate, or make available a database-as-a-
|
|
15
|
+
service, hosted API, managed database platform, or any
|
|
16
|
+
substantially similar hosted service for third parties.
|
|
17
|
+
|
|
18
|
+
The Additional Use Grant does not permit using the
|
|
19
|
+
Licensed Work to provide a commercial or non-commercial
|
|
20
|
+
hosted service that allows third parties to access LoraDB
|
|
21
|
+
functionality, including as part of a competing managed
|
|
22
|
+
database platform, backend-as-a-service, application
|
|
23
|
+
platform, developer platform, or resale offering.
|
|
24
|
+
|
|
25
|
+
Business Source License
|
|
26
|
+
|
|
27
|
+
Terms
|
|
28
|
+
|
|
29
|
+
The Licensor hereby grants you the right to copy, modify, create derivative
|
|
30
|
+
works, redistribute, and make non-production use of the Licensed Work. The
|
|
31
|
+
Licensor may make an Additional Use Grant, above, permitting limited production
|
|
32
|
+
use.
|
|
33
|
+
|
|
34
|
+
Effective on the Change Date, or the fourth anniversary of the first publicly
|
|
35
|
+
available distribution of a specific version of the Licensed Work under this
|
|
36
|
+
License, whichever comes first, the Licensor hereby grants you rights under
|
|
37
|
+
the terms of the Change License, and the rights granted in the paragraph
|
|
38
|
+
above terminate.
|
|
39
|
+
|
|
40
|
+
If your use of the Licensed Work does not comply with the requirements
|
|
41
|
+
currently in effect as described in this License, you must purchase a
|
|
42
|
+
commercial license from the Licensor, its affiliated entities, or authorized
|
|
43
|
+
resellers, or you must refrain from using the Licensed Work.
|
|
44
|
+
|
|
45
|
+
All copies of the original and modified Licensed Work, and derivative works
|
|
46
|
+
of the Licensed Work, are subject to this License. This License applies
|
|
47
|
+
separately for each version of the Licensed Work and the Change Date may vary
|
|
48
|
+
for each version of the Licensed Work released by Licensor.
|
|
49
|
+
|
|
50
|
+
You must conspicuously display this License on each original or modified copy
|
|
51
|
+
of the Licensed Work. If you receive the Licensed Work in original or modified
|
|
52
|
+
form from a third party, the terms and conditions set forth in this License
|
|
53
|
+
apply to your use of that work.
|
|
54
|
+
|
|
55
|
+
Any use of the Licensed Work in violation of this License will automatically
|
|
56
|
+
terminate your rights under this License for the current and all other
|
|
57
|
+
versions of the Licensed Work.
|
|
58
|
+
|
|
59
|
+
This License does not grant you any right in any trademark or logo of Licensor
|
|
60
|
+
or its affiliates.
|
|
61
|
+
|
|
62
|
+
TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
|
|
63
|
+
AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
|
|
64
|
+
EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF MERCHANTABILITY,
|
|
65
|
+
FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND TITLE.
|
|
66
|
+
|
|
67
|
+
MariaDB hereby grants you permission to use this License's text to license
|
|
68
|
+
your works, and to refer to it using the trademark "Business Source License",
|
|
69
|
+
as long as you comply with the Covenants of Licensor below.
|
|
70
|
+
|
|
71
|
+
Covenants of Licensor
|
|
72
|
+
|
|
73
|
+
In consideration of the right to use this License's text and the "Business
|
|
74
|
+
Source License" name and trademark, Licensor covenants to MariaDB, and to all
|
|
75
|
+
other recipients of the licensed work to be provided by Licensor:
|
|
76
|
+
|
|
77
|
+
1. To specify as the Change License the GPL Version 2.0 or any later version,
|
|
78
|
+
or a license that is compatible with GPL Version 2.0 or a later version,
|
|
79
|
+
where "compatible" means that software provided under the Change License can
|
|
80
|
+
be included in a program with software provided under GPL Version 2.0 or a
|
|
81
|
+
later version. Licensor may specify additional Change Licenses without
|
|
82
|
+
limitation.
|
|
83
|
+
2. To either: (a) specify an additional grant of rights to use that does not
|
|
84
|
+
impose any additional restriction on the right granted in this License, as
|
|
85
|
+
the Additional Use Grant; or (b) insert the text "None".
|
|
86
|
+
3. To specify a Change Date.
|
|
87
|
+
4. Not to modify this License in any other way.
|
data/README.md
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# lora-ruby
|
|
2
|
+
|
|
3
|
+
Ruby bindings for the [Lora](../../README.md) in-memory graph engine.
|
|
4
|
+
Ships a native extension built with [Magnus](https://github.com/matsadler/magnus)
|
|
5
|
+
on top of [`rb-sys`](https://github.com/oxidize-rb/rb-sys) so the Rust
|
|
6
|
+
engine runs in-process — no separate server, no socket hop.
|
|
7
|
+
|
|
8
|
+
> **Status:** prototype / feasibility check. Published source gem on
|
|
9
|
+
> RubyGems; precompiled platform gems are built for the supported
|
|
10
|
+
> targets (see "Release" below).
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
gem install lora-ruby
|
|
16
|
+
# or in a Gemfile
|
|
17
|
+
gem "lora-ruby"
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`require "lora_ruby"` loads the native extension from
|
|
21
|
+
`lib/lora_ruby/lora_ruby.{so,bundle,dll}`. If a precompiled gem for
|
|
22
|
+
your platform exists on RubyGems, the install is a direct download; if
|
|
23
|
+
not, the source gem is built locally with `cargo` and a stable Rust
|
|
24
|
+
toolchain (1.87+).
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
```ruby
|
|
29
|
+
require "lora_ruby"
|
|
30
|
+
|
|
31
|
+
db = LoraRuby::Database.create
|
|
32
|
+
|
|
33
|
+
db.execute("CREATE (:Person {name: $n, age: $a})", { n: "Alice", a: 30 })
|
|
34
|
+
|
|
35
|
+
result = db.execute("MATCH (n:Person) RETURN n")
|
|
36
|
+
result["rows"].each do |row|
|
|
37
|
+
n = row["n"]
|
|
38
|
+
puts n["properties"]["name"] if LoraRuby.node?(n)
|
|
39
|
+
end
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Params
|
|
43
|
+
|
|
44
|
+
`execute` accepts a second argument — either `nil` or a `Hash` keyed by
|
|
45
|
+
parameter name (`String` or `Symbol`). Values can be any of:
|
|
46
|
+
|
|
47
|
+
- `nil`, `true`, `false`, `Integer`, `Float`, `String`, `Symbol` (stringified)
|
|
48
|
+
- `Array` of the above (recursive)
|
|
49
|
+
- `Hash` keyed by `String`/`Symbol` with the above values (recursive)
|
|
50
|
+
- Tagged temporal/spatial Hashes produced by the constructors below
|
|
51
|
+
|
|
52
|
+
## Module shape — why `LoraRuby::Database`?
|
|
53
|
+
|
|
54
|
+
Three reasonable options were considered:
|
|
55
|
+
|
|
56
|
+
- `LoraRuby::Database` — matches the gem filename; scope is obvious.
|
|
57
|
+
- `LoraDB::Database` — matches the brand (loradb.com).
|
|
58
|
+
- `Lora::Database` — shortest, but collides with arbitrary "lora" apps.
|
|
59
|
+
|
|
60
|
+
We went with **`LoraRuby::Database`** for symmetry with the Python
|
|
61
|
+
binding's `lora_python.Database` and because it mirrors the
|
|
62
|
+
`require "lora_ruby"` path exactly. The gem name on RubyGems is
|
|
63
|
+
`lora-ruby` (hyphen); the Ruby constant follows Rubocop convention
|
|
64
|
+
(CamelCase, no hyphen).
|
|
65
|
+
|
|
66
|
+
## Public API
|
|
67
|
+
|
|
68
|
+
```ruby
|
|
69
|
+
LoraRuby::Database.create # -> Database
|
|
70
|
+
LoraRuby::Database.new # -> Database (alias of .create)
|
|
71
|
+
|
|
72
|
+
db.execute(query, params = nil) # -> { "columns" => [...], "rows" => [...] }
|
|
73
|
+
db.clear # -> nil
|
|
74
|
+
db.node_count # -> Integer
|
|
75
|
+
db.relationship_count # -> Integer
|
|
76
|
+
|
|
77
|
+
LoraRuby::VERSION # gem version
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Result shape:
|
|
81
|
+
|
|
82
|
+
```ruby
|
|
83
|
+
{
|
|
84
|
+
"columns" => ["name"],
|
|
85
|
+
"rows" => [{ "name" => "Alice" }],
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Hash keys on the output are always **strings**, matching the `lora-node`,
|
|
90
|
+
`lora-wasm`, and `lora-python` bindings. Input Hashes accept either
|
|
91
|
+
symbol or string keys — both work for param names and for tagged
|
|
92
|
+
constructor Hashes like `point`/`date`/...
|
|
93
|
+
|
|
94
|
+
## Typed value model
|
|
95
|
+
|
|
96
|
+
Identical contract to the other bindings:
|
|
97
|
+
|
|
98
|
+
| Ruby shape | Lora value |
|
|
99
|
+
|-------------------------------------------------------------------------|-------------------|
|
|
100
|
+
| `nil`, `true`/`false`, `Integer`, `Float`, `String` | scalars |
|
|
101
|
+
| `Array`, `Hash` | collections |
|
|
102
|
+
| `{"kind" => "node", "id", "labels", "properties"}` | node |
|
|
103
|
+
| `{"kind" => "relationship", "id", …}` | relationship |
|
|
104
|
+
| `{"kind" => "path", "nodes" => [...], "rels" => [...]}` | path |
|
|
105
|
+
| `{"kind" => "date", "iso" => "YYYY-MM-DD"}` (and `time`, …) | temporal |
|
|
106
|
+
| point Hashes (below) | point |
|
|
107
|
+
|
|
108
|
+
Points are returned as Hashes keyed on their CRS:
|
|
109
|
+
|
|
110
|
+
| SRID | Hash |
|
|
111
|
+
|------|------------------------------------------------------------------------------------------------------------|
|
|
112
|
+
| 7203 | `{"kind"=>"point","srid"=>7203,"crs"=>"cartesian","x","y"}` |
|
|
113
|
+
| 9157 | `{"kind"=>"point","srid"=>9157,"crs"=>"cartesian-3D","x","y","z"}` |
|
|
114
|
+
| 4326 | `{"kind"=>"point","srid"=>4326,"crs"=>"WGS-84-2D","x","y","longitude","latitude"}` |
|
|
115
|
+
| 4979 | `{"kind"=>"point","srid"=>4979,"crs"=>"WGS-84-3D","x","y","z","longitude","latitude","height"}` |
|
|
116
|
+
|
|
117
|
+
### Constructors and guards
|
|
118
|
+
|
|
119
|
+
Re-exported on both `LoraRuby` and `LoraRuby::Types`:
|
|
120
|
+
|
|
121
|
+
- Constructors: `date`, `time`, `localtime`, `datetime`,
|
|
122
|
+
`localdatetime`, `duration`, `cartesian`, `cartesian_3d`, `wgs84`,
|
|
123
|
+
`wgs84_3d`.
|
|
124
|
+
- Guards: `node?`, `relationship?`, `path?`, `point?`, `temporal?`.
|
|
125
|
+
|
|
126
|
+
```ruby
|
|
127
|
+
db.execute(
|
|
128
|
+
"CREATE (:Event {on: $d, at: $c})",
|
|
129
|
+
{ d: LoraRuby.date("2025-03-14"), c: LoraRuby.cartesian(1.5, 2.5) },
|
|
130
|
+
)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Errors
|
|
134
|
+
|
|
135
|
+
- `LoraRuby::Error` — base class (extends `StandardError`).
|
|
136
|
+
- `LoraRuby::QueryError` — parse / analyze / execute failure.
|
|
137
|
+
- `LoraRuby::InvalidParamsError` — a parameter value couldn't be mapped.
|
|
138
|
+
|
|
139
|
+
## Concurrency (GVL release)
|
|
140
|
+
|
|
141
|
+
`Database#execute` calls `rb_thread_call_without_gvl`, so other Ruby
|
|
142
|
+
threads run while the engine is busy. Concurrent queries against the
|
|
143
|
+
same `Database` serialise on an internal `Mutex`; parallel queries
|
|
144
|
+
against **different** `Database` instances have no shared state.
|
|
145
|
+
|
|
146
|
+
The engine has no cancellation hook, so we pass a `NULL` unblock
|
|
147
|
+
function. A thread interrupted mid-query (`Thread#kill`) will observe
|
|
148
|
+
the interrupt **after** the current query finishes. Keep queries short
|
|
149
|
+
if you rely on cooperative cancellation.
|
|
150
|
+
|
|
151
|
+
## Local development
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
cd crates/lora-ruby
|
|
155
|
+
bundle install
|
|
156
|
+
bundle exec rake compile # cargo build → lib/lora_ruby/lora_ruby.<ext>
|
|
157
|
+
bundle exec rake test # minitest
|
|
158
|
+
bundle exec rake build # pkg/lora-ruby-<version>.gem
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
`rake compile` drives `cargo` through `rb_sys/extensiontask`; it is
|
|
162
|
+
what `gem install` runs on end-user machines that don't have a
|
|
163
|
+
precompiled platform gem.
|
|
164
|
+
|
|
165
|
+
## Architecture
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
lora-database (Rust, embedded)
|
|
169
|
+
└── crates/lora-ruby/ (gem root + cargo crate)
|
|
170
|
+
├── Cargo.toml Rust workspace member
|
|
171
|
+
├── extconf.rb rb-sys / mkmf entry point
|
|
172
|
+
├── src/lib.rs <- Magnus / rb-sys bindings
|
|
173
|
+
└── lib/lora_ruby/
|
|
174
|
+
├── lora_ruby.<ext> (native, built by rake compile)
|
|
175
|
+
├── types.rb tagged-dict constructors + guards
|
|
176
|
+
└── version.rb gem version
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
rb-sys' convention keeps `Cargo.toml` and `extconf.rb` side by side so
|
|
180
|
+
the cargo manifest directory IS the gem root. That makes the crate
|
|
181
|
+
a first-class Cargo workspace member (shared `Cargo.lock`,
|
|
182
|
+
`target/`, `cargo check --workspace` coverage) without a nested
|
|
183
|
+
`ext/<name>/` directory.
|
|
184
|
+
|
|
185
|
+
## Release
|
|
186
|
+
|
|
187
|
+
Source gem is always built. Precompiled platform gems are emitted via
|
|
188
|
+
`rb_sys/cross` for `{x86_64,aarch64}-linux`, `{x86_64,arm64}-darwin`, and
|
|
189
|
+
`x64-mingw-ucrt`. See `.github/workflows/packages-release.yml` (Ruby
|
|
190
|
+
section) and `RELEASING.md`.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LoraRuby
|
|
4
|
+
# Shared value model — aligned with the `LoraValue` contract used by
|
|
5
|
+
# `lora-node`, `lora-wasm`, and `lora-python`.
|
|
6
|
+
#
|
|
7
|
+
# - Scalars pass through as Ruby natives (`nil`, `true`, `false`,
|
|
8
|
+
# `Integer`, `Float`, `String`).
|
|
9
|
+
# - Lists and maps come back as `Array` / `Hash` (string keys).
|
|
10
|
+
# - Graph, temporal, and spatial values come back as plain `Hash`es
|
|
11
|
+
# with a `"kind"` discriminator.
|
|
12
|
+
#
|
|
13
|
+
# If you want to narrow a value explicitly, use the `node?` / `point?`
|
|
14
|
+
# / `temporal?` helpers below.
|
|
15
|
+
module Types
|
|
16
|
+
SRID_CARTESIAN_2D = 7203
|
|
17
|
+
SRID_CARTESIAN_3D = 9157
|
|
18
|
+
SRID_WGS84_2D = 4326
|
|
19
|
+
SRID_WGS84_3D = 4979
|
|
20
|
+
|
|
21
|
+
CRS_CARTESIAN_2D = "cartesian"
|
|
22
|
+
CRS_CARTESIAN_3D = "cartesian-3D"
|
|
23
|
+
CRS_WGS84_2D = "WGS-84-2D"
|
|
24
|
+
CRS_WGS84_3D = "WGS-84-3D"
|
|
25
|
+
|
|
26
|
+
TEMPORAL_KINDS = %w[date time localtime datetime localdatetime duration].freeze
|
|
27
|
+
|
|
28
|
+
VECTOR_COORD_TYPES = %w[FLOAT64 FLOAT32 INTEGER INTEGER32 INTEGER16 INTEGER8].freeze
|
|
29
|
+
|
|
30
|
+
module_function
|
|
31
|
+
|
|
32
|
+
# ------------------------------------------------------------------
|
|
33
|
+
# Temporal constructors — ISO-8601 tagged Hashes. The native
|
|
34
|
+
# extension normalises + validates these on the way into the engine;
|
|
35
|
+
# invalid ISO strings raise `LoraRuby::InvalidParamsError`.
|
|
36
|
+
# ------------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
def date(iso) = { "kind" => "date", "iso" => iso }
|
|
39
|
+
def time(iso) = { "kind" => "time", "iso" => iso }
|
|
40
|
+
def localtime(iso) = { "kind" => "localtime", "iso" => iso }
|
|
41
|
+
def datetime(iso) = { "kind" => "datetime", "iso" => iso }
|
|
42
|
+
def localdatetime(iso) = { "kind" => "localdatetime", "iso" => iso }
|
|
43
|
+
def duration(iso) = { "kind" => "duration", "iso" => iso }
|
|
44
|
+
|
|
45
|
+
# ------------------------------------------------------------------
|
|
46
|
+
# Vector constructor — returns the canonical tagged Hash that the
|
|
47
|
+
# engine accepts as a VECTOR parameter and emits on return.
|
|
48
|
+
# ------------------------------------------------------------------
|
|
49
|
+
|
|
50
|
+
def vector(values, dimension, coordinate_type)
|
|
51
|
+
{
|
|
52
|
+
"kind" => "vector",
|
|
53
|
+
"dimension" => dimension,
|
|
54
|
+
"coordinateType" => coordinate_type.to_s,
|
|
55
|
+
"values" => values.dup,
|
|
56
|
+
}
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# ------------------------------------------------------------------
|
|
60
|
+
# Spatial constructors — mirrors lora_python.cartesian / wgs84.
|
|
61
|
+
# `cartesian(1, 2)` returns a 2D cartesian point; use `cartesian_3d`
|
|
62
|
+
# for the 3D variant. WGS-84 variants carry `longitude` / `latitude`
|
|
63
|
+
# aliases alongside `x` / `y` so result-side consumers can read
|
|
64
|
+
# either without conversion.
|
|
65
|
+
# ------------------------------------------------------------------
|
|
66
|
+
|
|
67
|
+
def cartesian(x, y)
|
|
68
|
+
{
|
|
69
|
+
"kind" => "point",
|
|
70
|
+
"srid" => SRID_CARTESIAN_2D,
|
|
71
|
+
"crs" => CRS_CARTESIAN_2D,
|
|
72
|
+
"x" => x.to_f,
|
|
73
|
+
"y" => y.to_f,
|
|
74
|
+
}
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def cartesian_3d(x, y, z)
|
|
78
|
+
{
|
|
79
|
+
"kind" => "point",
|
|
80
|
+
"srid" => SRID_CARTESIAN_3D,
|
|
81
|
+
"crs" => CRS_CARTESIAN_3D,
|
|
82
|
+
"x" => x.to_f,
|
|
83
|
+
"y" => y.to_f,
|
|
84
|
+
"z" => z.to_f,
|
|
85
|
+
}
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def wgs84(longitude, latitude)
|
|
89
|
+
{
|
|
90
|
+
"kind" => "point",
|
|
91
|
+
"srid" => SRID_WGS84_2D,
|
|
92
|
+
"crs" => CRS_WGS84_2D,
|
|
93
|
+
"x" => longitude.to_f,
|
|
94
|
+
"y" => latitude.to_f,
|
|
95
|
+
"longitude" => longitude.to_f,
|
|
96
|
+
"latitude" => latitude.to_f,
|
|
97
|
+
}
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def wgs84_3d(longitude, latitude, height)
|
|
101
|
+
{
|
|
102
|
+
"kind" => "point",
|
|
103
|
+
"srid" => SRID_WGS84_3D,
|
|
104
|
+
"crs" => CRS_WGS84_3D,
|
|
105
|
+
"x" => longitude.to_f,
|
|
106
|
+
"y" => latitude.to_f,
|
|
107
|
+
"z" => height.to_f,
|
|
108
|
+
"longitude" => longitude.to_f,
|
|
109
|
+
"latitude" => latitude.to_f,
|
|
110
|
+
"height" => height.to_f,
|
|
111
|
+
}
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# ------------------------------------------------------------------
|
|
115
|
+
# Guards — duck-typed narrowing helpers. Accept symbol-keyed and
|
|
116
|
+
# string-keyed Hashes because that's what callers might build up
|
|
117
|
+
# manually (the native extension always emits string keys).
|
|
118
|
+
# ------------------------------------------------------------------
|
|
119
|
+
|
|
120
|
+
def node?(v) = tagged?(v, "node")
|
|
121
|
+
def relationship?(v) = tagged?(v, "relationship")
|
|
122
|
+
def path?(v) = tagged?(v, "path")
|
|
123
|
+
def point?(v) = tagged?(v, "point")
|
|
124
|
+
def vector?(v) = tagged?(v, "vector")
|
|
125
|
+
|
|
126
|
+
def temporal?(v)
|
|
127
|
+
return false unless v.is_a?(Hash)
|
|
128
|
+
TEMPORAL_KINDS.include?(kind_of(v))
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def tagged?(v, expected)
|
|
132
|
+
return false unless v.is_a?(Hash)
|
|
133
|
+
kind_of(v) == expected
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def kind_of(hash)
|
|
137
|
+
hash["kind"] || hash[:kind]
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module LoraRuby
|
|
4
|
+
# Gem version — kept in lockstep with the workspace Cargo.toml version
|
|
5
|
+
# by `scripts/sync-versions.mjs`. The native extension also defines
|
|
6
|
+
# `LoraRuby::VERSION` (from Cargo's `CARGO_PKG_VERSION`); we pre-seed
|
|
7
|
+
# the constant here so `require "lora_ruby/version"` works during
|
|
8
|
+
# `gem build` / `bundle install` before the `.so` has been compiled.
|
|
9
|
+
#
|
|
10
|
+
# Guard against redefinition so re-requiring this file (or loading
|
|
11
|
+
# both paths) doesn't emit a "warning: already initialized constant"
|
|
12
|
+
# when the native extension loads second with the identical value.
|
|
13
|
+
VERSION = "0.2.0" unless const_defined?(:VERSION)
|
|
14
|
+
end
|
data/lib/lora_ruby.rb
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Public entry point for the gem. Users `require "lora_ruby"` which
|
|
4
|
+
# loads the native extension and re-exports the public API.
|
|
5
|
+
#
|
|
6
|
+
# require "lora_ruby"
|
|
7
|
+
#
|
|
8
|
+
# db = LoraRuby::Database.create
|
|
9
|
+
# db.execute("CREATE (:Person {name: $n})", { n: "Alice" })
|
|
10
|
+
# result = db.execute("MATCH (n:Person) RETURN n.name AS name")
|
|
11
|
+
# result["rows"] # => [{"name" => "Alice"}]
|
|
12
|
+
|
|
13
|
+
require_relative "lora_ruby/version"
|
|
14
|
+
|
|
15
|
+
# Load the native extension. rb-sys builds it under the gem's extension
|
|
16
|
+
# directory and installs it to lib/lora_ruby/lora_ruby.{so,bundle,dll}
|
|
17
|
+
# from extconf.rb's create_rust_makefile("lora_ruby/lora_ruby").
|
|
18
|
+
require "lora_ruby/lora_ruby"
|
|
19
|
+
|
|
20
|
+
require_relative "lora_ruby/types"
|
|
21
|
+
|
|
22
|
+
module LoraRuby
|
|
23
|
+
# Top-level sugar so callers can write `LoraRuby.cartesian(...)`
|
|
24
|
+
# without having to say `LoraRuby::Types.cartesian(...)`. Same
|
|
25
|
+
# trade-off `lora_python.types` makes.
|
|
26
|
+
#
|
|
27
|
+
# We explicitly re-export each method rather than `extend Types`
|
|
28
|
+
# because `Types`' methods are declared with `module_function`,
|
|
29
|
+
# which makes them public module methods on `Types` itself but
|
|
30
|
+
# private instance methods — extending would copy them over as
|
|
31
|
+
# private singletons on `LoraRuby`, which isn't the intended UX.
|
|
32
|
+
%i[
|
|
33
|
+
date time localtime datetime localdatetime duration
|
|
34
|
+
cartesian cartesian_3d wgs84 wgs84_3d
|
|
35
|
+
vector
|
|
36
|
+
node? relationship? path? point? temporal? vector?
|
|
37
|
+
].each do |m|
|
|
38
|
+
define_singleton_method(m) do |*args, **kwargs|
|
|
39
|
+
if kwargs.empty?
|
|
40
|
+
Types.public_send(m, *args)
|
|
41
|
+
else
|
|
42
|
+
Types.public_send(m, *args, **kwargs)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: lora-ruby
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.2.0
|
|
5
|
+
platform: x86_64-linux
|
|
6
|
+
authors:
|
|
7
|
+
- LoraDB, Inc.
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-04-24 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: rake
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '13.2'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '13.2'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rake-compiler
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '1.2'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '1.2'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: minitest
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '5.20'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '5.20'
|
|
55
|
+
description: Ruby bindings for the Lora in-memory graph database. Exposes the embedded
|
|
56
|
+
Rust engine as a native extension via Magnus/rb-sys, so queries run in-process without
|
|
57
|
+
a separate server.
|
|
58
|
+
email:
|
|
59
|
+
executables: []
|
|
60
|
+
extensions: []
|
|
61
|
+
extra_rdoc_files: []
|
|
62
|
+
files:
|
|
63
|
+
- LICENSE
|
|
64
|
+
- README.md
|
|
65
|
+
- lib/lora_ruby.rb
|
|
66
|
+
- lib/lora_ruby/3.1/lora_ruby.so
|
|
67
|
+
- lib/lora_ruby/3.2/lora_ruby.so
|
|
68
|
+
- lib/lora_ruby/3.3/lora_ruby.so
|
|
69
|
+
- lib/lora_ruby/types.rb
|
|
70
|
+
- lib/lora_ruby/version.rb
|
|
71
|
+
homepage: https://github.com/lora-db/lora
|
|
72
|
+
licenses:
|
|
73
|
+
- BUSL-1.1
|
|
74
|
+
metadata:
|
|
75
|
+
homepage_uri: https://github.com/lora-db/lora
|
|
76
|
+
source_code_uri: https://github.com/lora-db/lora/tree/main/crates/lora-ruby
|
|
77
|
+
bug_tracker_uri: https://github.com/lora-db/lora/issues
|
|
78
|
+
documentation_uri: https://github.com/lora-db/lora/blob/main/crates/lora-ruby/README.md
|
|
79
|
+
rubygems_mfa_required: 'true'
|
|
80
|
+
post_install_message:
|
|
81
|
+
rdoc_options: []
|
|
82
|
+
require_paths:
|
|
83
|
+
- lib
|
|
84
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - ">="
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '3.1'
|
|
89
|
+
- - "<"
|
|
90
|
+
- !ruby/object:Gem::Version
|
|
91
|
+
version: 3.4.dev
|
|
92
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - ">="
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: 3.3.11
|
|
97
|
+
requirements: []
|
|
98
|
+
rubygems_version: 3.5.23
|
|
99
|
+
signing_key:
|
|
100
|
+
specification_version: 4
|
|
101
|
+
summary: Ruby bindings for the Lora in-memory graph database
|
|
102
|
+
test_files: []
|