sqlite_crypto 2.1.0 → 2.3.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 +4 -4
- data/CHANGELOG.md +33 -1
- data/README.md +33 -11
- data/lib/sqlite_crypto/id_types.rb +31 -0
- data/lib/sqlite_crypto/migration_helpers.rb +10 -6
- data/lib/sqlite_crypto/model_extensions.rb +8 -4
- data/lib/sqlite_crypto/schema_dumper.rb +6 -5
- data/lib/sqlite_crypto/sqlite3_adapter_extension.rb +4 -2
- data/lib/sqlite_crypto/type/base.rb +2 -3
- data/lib/sqlite_crypto/type/ulid.rb +2 -1
- data/lib/sqlite_crypto/version.rb +1 -1
- data/lib/sqlite_crypto.rb +1 -0
- metadata +19 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5092437393d977d0bc5bd3ab75fec48c2518ff2ab0296bf6bb1abc42cdd1dfd9
|
|
4
|
+
data.tar.gz: 85e2ba284a68ee0cdf113895771788e5d60ee324631672f414f96756f08c5a9c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 66a702bb87cf9ebb082a4f0a727df6fd3f8232e47295cf5d56d3e7a03d7604c29d7692ddd556753a4cf9a0e1076885273b748c65e67adede97f0cc8e44e7718e
|
|
7
|
+
data.tar.gz: 2d6c01a90e63dfd79947c010de863c0b0180c83056d5c72a7d9a6dd0a3e901c5ecebb6ff91c2c78c589e22a108b3183d9d382be612346ac5f3c23262fffd342d
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,38 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.3.0] - 2026-07-15
|
|
9
|
+
|
|
10
|
+
### Security
|
|
11
|
+
- Refreshed lockfiles, picking up fixes for transitive CVEs in `sqlite3`, `nokogiri`, `json`, `crass`, and `concurrent-ruby`
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
- Updated `.ruby-version` from `4.0.3` to `4.0.6`
|
|
15
|
+
- CI: cache bundler installs per Rails version, run `bundler-audit` from the bundle, and drop the empty coverage-threshold step
|
|
16
|
+
- Narrowed the runtime dependency from `rails` to `activerecord` + `railties`, dropping the `action_text-trix` pin it required
|
|
17
|
+
- **Tightened ULID validation**: rejects `I`, `L`, `O`, `U`, which Crockford base32 excludes
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
- **Reads no longer raise on malformed legacy IDs**: `Type::Base#deserialize` returns stored values as-is instead of re-validating them, so a corrupted row no longer crashes every read of it. Writes (`#cast`/`#serialize`) still validate strictly
|
|
21
|
+
- **Primary-key type cache invalidation**: `_sqlite_crypto_pk_type` now clears on `reset_column_information` instead of going stale after a migration
|
|
22
|
+
- **Adapter guard for auto ID generation**: primary-key detection now only applies to SQLite3 connections, not any string(36/26) primary key regardless of adapter
|
|
23
|
+
- **`references`/`belongs_to` with `to_table` and `foreign_key: true`**: the foreign key now targets the correct table instead of the pluralized association name
|
|
24
|
+
|
|
25
|
+
## [2.2.0] - 2026-05-08
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
- **Theme-aware README logo**: Added dark-mode/light-mode logo switching via `<picture>` in `README.md`
|
|
29
|
+
- **Shared ID type mapping module**: Added `SqliteCrypto::IdTypes` to centralize UUID/ULID limit and type detection logic
|
|
30
|
+
- Unit specs for `SqliteCrypto::IdTypes`
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
- Refactored schema dumper, migration helpers, model extensions, and SQLite adapter extension to use `SqliteCrypto::IdTypes`
|
|
34
|
+
- Updated `.ruby-version` from `4.0.0` to `4.0.3`
|
|
35
|
+
- Refreshed README badges and compatibility notes
|
|
36
|
+
|
|
37
|
+
### Fixed
|
|
38
|
+
- Removed repeated migration fixture loading warning by replacing `load` with `require_relative` in migration integration spec
|
|
39
|
+
|
|
8
40
|
## [2.1.0] - 2026-03-22
|
|
9
41
|
|
|
10
42
|
### Added
|
|
@@ -156,4 +188,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
156
188
|
### Fixed
|
|
157
189
|
- Rails version compatibility for migrations (supports Rails 7.1 through 8.1)
|
|
158
190
|
- Schema dumper prepend timing by loading sqlite3_adapter explicitly
|
|
159
|
-
- ULID foreign key detection with proper table name pluralization
|
|
191
|
+
- ULID foreign key detection with proper table name pluralization
|
data/README.md
CHANGED
|
@@ -1,11 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<picture>
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset=".github/workflows/logo_dark.svg">
|
|
4
|
+
<source media="(prefers-color-scheme: light)" srcset=".github/workflows/logo_light.svg">
|
|
5
|
+
<img alt="sqlite_crypto logo" src=".github/workflows/logo_light.svg" width="220">
|
|
6
|
+
</picture>
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
<p align="center">
|
|
10
|
+
<a href="https://github.com/bart-oz/sqlite_crypto/releases">
|
|
11
|
+
<img src="https://img.shields.io/badge/version-2.3.0-blue.svg" alt="Version">
|
|
12
|
+
</a>
|
|
13
|
+
<a href="LICENSE.txt">
|
|
14
|
+
<img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License">
|
|
15
|
+
</a>
|
|
16
|
+
<a href="https://github.com/bart-oz/sqlite_crypto">
|
|
17
|
+
<img src="https://img.shields.io/badge/types-ULID,_UUIDv7/v4-brightgreen.svg" alt="Types supported">
|
|
18
|
+
</a>
|
|
19
|
+
<a href="https://github.com/bart-oz/sqlite_crypto/actions/workflows/ci.yml">
|
|
20
|
+
<img src="https://github.com/bart-oz/sqlite_crypto/actions/workflows/ci.yml/badge.svg" alt="Tests">
|
|
21
|
+
</a>
|
|
22
|
+
<a href="https://github.com/bart-oz/sqlite_crypto">
|
|
23
|
+
<img src="https://img.shields.io/badge/status-active-success.svg" alt="Status">
|
|
24
|
+
</a>
|
|
25
|
+
</p>
|
|
9
26
|
|
|
10
27
|
## Overview
|
|
11
28
|
|
|
@@ -24,11 +41,11 @@ end
|
|
|
24
41
|
- Automatic foreign key type detection
|
|
25
42
|
- Model-level ID generation
|
|
26
43
|
- Clean schema.rb output
|
|
27
|
-
-
|
|
44
|
+
- Lightweight runtime dependencies (`activerecord`, `railties`, `sqlite3`, `ulid` — no full `rails` metagem)
|
|
28
45
|
|
|
29
46
|
## Compatibility
|
|
30
47
|
|
|
31
|
-
**Ruby & Rails:**
|
|
48
|
+
**Ruby & Rails tested in CI:**
|
|
32
49
|
|
|
33
50
|
| | Rails 7.1 | Rails 7.2 | Rails 8.0 | Rails 8.1 |
|
|
34
51
|
|-------|-----------|-----------|-----------|-----------|
|
|
@@ -38,6 +55,11 @@ end
|
|
|
38
55
|
| Ruby 3.4 | ✓ | ✓ | ✓ | ✓ |
|
|
39
56
|
| Ruby 4.0 | ✓ | ✓ | ✓ | ✓ |
|
|
40
57
|
|
|
58
|
+
**Upstream lifecycle note (as of 2026-07-15):**
|
|
59
|
+
- Ruby 3.1 is EOL; Ruby 3.2 is EOL. Latest stable Ruby is 4.0.6.
|
|
60
|
+
- Rails 7.1 is EOL.
|
|
61
|
+
- Rails 7.2 is security-fixes-only; Rails 8.0 and 8.1 are actively supported.
|
|
62
|
+
|
|
41
63
|
**UUID Versions:**
|
|
42
64
|
|
|
43
65
|
| Version | Ruby 3.1/3.2 | Ruby 3.3+ |
|
|
@@ -237,4 +259,4 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/bart-o
|
|
|
237
259
|
|
|
238
260
|
## License
|
|
239
261
|
|
|
240
|
-
The gem is available as open source under the terms of the [MIT License](LICENSE.txt).
|
|
262
|
+
The gem is available as open source under the terms of the [MIT License](LICENSE.txt).
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SqliteCrypto
|
|
4
|
+
module IdTypes
|
|
5
|
+
UUID_LENGTH = 36
|
|
6
|
+
ULID_LENGTH = 26
|
|
7
|
+
|
|
8
|
+
TYPE_TO_LIMIT = {
|
|
9
|
+
uuid: UUID_LENGTH,
|
|
10
|
+
ulid: ULID_LENGTH
|
|
11
|
+
}.freeze
|
|
12
|
+
LIMIT_TO_TYPE = TYPE_TO_LIMIT.invert.freeze
|
|
13
|
+
|
|
14
|
+
module_function
|
|
15
|
+
|
|
16
|
+
def string_limit_for(type)
|
|
17
|
+
TYPE_TO_LIMIT[type]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def type_from_string_limit(limit)
|
|
21
|
+
LIMIT_TO_TYPE[limit]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def type_from_sql_type(sql_type)
|
|
25
|
+
case sql_type.to_s.downcase
|
|
26
|
+
when "varchar(#{UUID_LENGTH})", "uuid" then :uuid
|
|
27
|
+
when "varchar(#{ULID_LENGTH})", "ulid" then :ulid
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "active_record/connection_adapters/sqlite3_adapter"
|
|
4
|
+
require "sqlite_crypto/id_types"
|
|
4
5
|
|
|
5
6
|
module SqliteCrypto
|
|
6
7
|
module MigrationHelpers
|
|
@@ -17,11 +18,17 @@ module SqliteCrypto
|
|
|
17
18
|
module References
|
|
18
19
|
def references(*args, **options)
|
|
19
20
|
ref_name = args.first
|
|
20
|
-
|
|
21
|
+
explicit_to_table = options.delete(:to_table)
|
|
22
|
+
ref_table = explicit_to_table || ref_name.to_s.pluralize
|
|
21
23
|
|
|
22
24
|
if (primary_key_type = detect_primary_key_type(ref_table))
|
|
23
25
|
options[:type] ||= :string
|
|
24
|
-
options[:limit] ||= (primary_key_type
|
|
26
|
+
options[:limit] ||= IdTypes.string_limit_for(primary_key_type)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
if explicit_to_table && options[:foreign_key]
|
|
30
|
+
fk_options = options[:foreign_key].is_a?(Hash) ? options[:foreign_key] : {}
|
|
31
|
+
options[:foreign_key] = fk_options.reverse_merge(to_table: explicit_to_table)
|
|
25
32
|
end
|
|
26
33
|
|
|
27
34
|
super
|
|
@@ -43,10 +50,7 @@ module SqliteCrypto
|
|
|
43
50
|
pk_column = find_primary_key_column(table_name, conn)
|
|
44
51
|
return nil unless pk_column
|
|
45
52
|
|
|
46
|
-
|
|
47
|
-
when "varchar(36)", "uuid" then :uuid
|
|
48
|
-
when "varchar(26)", "ulid" then :ulid
|
|
49
|
-
end
|
|
53
|
+
IdTypes.type_from_sql_type(pk_column.sql_type)
|
|
50
54
|
end
|
|
51
55
|
|
|
52
56
|
def find_primary_key_column(table_name, conn)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "ulid"
|
|
4
|
+
require "sqlite_crypto/id_types"
|
|
4
5
|
|
|
5
6
|
module SqliteCrypto
|
|
6
7
|
module ModelExtensions
|
|
@@ -49,11 +50,17 @@ module SqliteCrypto
|
|
|
49
50
|
@_sqlite_crypto_pk_type = _detect_sqlite_crypto_pk_type
|
|
50
51
|
end
|
|
51
52
|
|
|
53
|
+
def reset_column_information
|
|
54
|
+
remove_instance_variable(:@_sqlite_crypto_pk_type) if defined?(@_sqlite_crypto_pk_type)
|
|
55
|
+
super
|
|
56
|
+
end
|
|
57
|
+
|
|
52
58
|
private
|
|
53
59
|
|
|
54
60
|
def _detect_sqlite_crypto_pk_type
|
|
55
61
|
return nil if abstract_class?
|
|
56
62
|
return nil unless table_exists?
|
|
63
|
+
return nil unless connection.adapter_name == "SQLite"
|
|
57
64
|
|
|
58
65
|
pk = primary_key
|
|
59
66
|
return nil unless pk
|
|
@@ -62,10 +69,7 @@ module SqliteCrypto
|
|
|
62
69
|
return nil unless column
|
|
63
70
|
return nil unless column.type == :string
|
|
64
71
|
|
|
65
|
-
|
|
66
|
-
when 36 then :uuid
|
|
67
|
-
when 26 then :ulid
|
|
68
|
-
end
|
|
72
|
+
IdTypes.type_from_string_limit(column.limit)
|
|
69
73
|
rescue ActiveRecord::StatementInvalid
|
|
70
74
|
nil
|
|
71
75
|
end
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "sqlite_crypto/id_types"
|
|
4
|
+
|
|
3
5
|
module SqliteCrypto
|
|
4
6
|
module SchemaDumper
|
|
5
7
|
private
|
|
@@ -7,11 +9,10 @@ module SqliteCrypto
|
|
|
7
9
|
def column_spec_for_primary_key(column)
|
|
8
10
|
return super unless column.name == "id" && column.type == :string
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
end
|
|
12
|
+
primary_key_type = IdTypes.type_from_string_limit(column.limit)
|
|
13
|
+
return super unless primary_key_type
|
|
14
|
+
|
|
15
|
+
{id: primary_key_type}
|
|
15
16
|
end
|
|
16
17
|
end
|
|
17
18
|
end
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "sqlite_crypto/id_types"
|
|
4
|
+
|
|
3
5
|
module SqliteCrypto
|
|
4
6
|
module Sqlite3AdapterExtension
|
|
5
7
|
def native_database_types
|
|
6
8
|
super.merge(
|
|
7
|
-
uuid: {name: "varchar", limit:
|
|
8
|
-
ulid: {name: "varchar", limit:
|
|
9
|
+
uuid: {name: "varchar", limit: IdTypes::UUID_LENGTH},
|
|
10
|
+
ulid: {name: "varchar", limit: IdTypes::ULID_LENGTH}
|
|
9
11
|
)
|
|
10
12
|
end
|
|
11
13
|
end
|
|
@@ -4,8 +4,7 @@ module SqliteCrypto
|
|
|
4
4
|
module Type
|
|
5
5
|
class Base < ActiveRecord::Type::String
|
|
6
6
|
def deserialize(value)
|
|
7
|
-
|
|
8
|
-
cast(value)
|
|
7
|
+
value&.to_s
|
|
9
8
|
end
|
|
10
9
|
|
|
11
10
|
def cast(value)
|
|
@@ -25,7 +24,7 @@ module SqliteCrypto
|
|
|
25
24
|
end
|
|
26
25
|
|
|
27
26
|
def changed_in_place?(raw_old_value, new_value)
|
|
28
|
-
|
|
27
|
+
deserialize(raw_old_value) != cast(new_value)
|
|
29
28
|
end
|
|
30
29
|
|
|
31
30
|
private
|
|
@@ -5,7 +5,8 @@ require "sqlite_crypto/type/base"
|
|
|
5
5
|
module SqliteCrypto
|
|
6
6
|
module Type
|
|
7
7
|
class ULID < Base
|
|
8
|
-
|
|
8
|
+
# Crockford base32 excludes I, L, O, U to avoid confusion with 1, 0.
|
|
9
|
+
ULID_PATTERN = /\A[0-7][0-9A-HJKMNP-TV-Z]{25}\z/i
|
|
9
10
|
|
|
10
11
|
def type
|
|
11
12
|
:ulid
|
data/lib/sqlite_crypto.rb
CHANGED
|
@@ -5,6 +5,7 @@ require "sqlite_crypto/configuration"
|
|
|
5
5
|
require "sqlite_crypto/railtie" if defined?(Rails)
|
|
6
6
|
require "sqlite_crypto/schema_dumper" if defined?(ActiveRecord)
|
|
7
7
|
require "sqlite_crypto/schema_definitions"
|
|
8
|
+
require "sqlite_crypto/id_types"
|
|
8
9
|
require "sqlite_crypto/generators/uuid"
|
|
9
10
|
|
|
10
11
|
module SqliteCrypto
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sqlite_crypto
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- BartOz
|
|
@@ -10,7 +10,21 @@ cert_chain: []
|
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
|
-
name:
|
|
13
|
+
name: activerecord
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: 7.1.0
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: 7.1.0
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: railties
|
|
14
28
|
requirement: !ruby/object:Gem::Requirement
|
|
15
29
|
requirements:
|
|
16
30
|
- - ">="
|
|
@@ -53,8 +67,7 @@ dependencies:
|
|
|
53
67
|
version: '1.0'
|
|
54
68
|
description: UUID and ULID primary key support for Rails with SQLite3. Provides automatic
|
|
55
69
|
type registration, validation, foreign key detection, and clean schema generation.
|
|
56
|
-
Supports UUIDv4 (random), UUIDv7 (time-ordered), and ULID (compact, time-sortable)
|
|
57
|
-
with zero external dependencies.
|
|
70
|
+
Supports UUIDv4 (random), UUIDv7 (time-ordered), and ULID (compact, time-sortable).
|
|
58
71
|
email:
|
|
59
72
|
- bartek.ozdoba@gmail.com
|
|
60
73
|
executables: []
|
|
@@ -69,6 +82,7 @@ files:
|
|
|
69
82
|
- lib/sqlite_crypto.rb
|
|
70
83
|
- lib/sqlite_crypto/configuration.rb
|
|
71
84
|
- lib/sqlite_crypto/generators/uuid.rb
|
|
85
|
+
- lib/sqlite_crypto/id_types.rb
|
|
72
86
|
- lib/sqlite_crypto/migration_helpers.rb
|
|
73
87
|
- lib/sqlite_crypto/model_extensions.rb
|
|
74
88
|
- lib/sqlite_crypto/railtie.rb
|
|
@@ -98,7 +112,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
98
112
|
- !ruby/object:Gem::Version
|
|
99
113
|
version: '0'
|
|
100
114
|
requirements: []
|
|
101
|
-
rubygems_version: 4.0.
|
|
115
|
+
rubygems_version: 4.0.16
|
|
102
116
|
specification_version: 4
|
|
103
117
|
summary: UUID (v4/v7) and ULID primary keys for Rails + SQLite3
|
|
104
118
|
test_files: []
|