rails-uuid-pk 0.1.0 → 0.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 +28 -0
- data/README.md +15 -27
- data/lib/generators/rails_uuid_pk/install/install_generator.rb +5 -8
- data/lib/rails_uuid_pk/migration_helpers.rb +45 -0
- data/lib/rails_uuid_pk/railtie.rb +34 -18
- data/lib/rails_uuid_pk/sqlite3_adapter_extension.rb +9 -0
- data/lib/rails_uuid_pk/type.rb +47 -0
- data/lib/rails_uuid_pk/version.rb +1 -1
- data/lib/rails_uuid_pk.rb +2 -0
- metadata +4 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d9552cdab44f5a5a6a4b699e12dc31ee13917ff74f0752f32e823dffed24e2e0
|
|
4
|
+
data.tar.gz: 6ddd7862945d8b13939be92990241539d93eaf754d6c47f2733d66eb2e29597e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 72fb9c050567562c0d01793d801d7633d45b26851734cb069b2e70ee74d8bf3387e515f50cb771fdbb46f8ad9b4cb767058739bad45050134ba710a8f6290201
|
|
7
|
+
data.tar.gz: ed3b396026fe6edc6485720d6d80af4d5fd11138652fea133515fcb8d931d9d38cf981553a46689121201922ee41b6fad5829c42c06783109b930b06acf41fda
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,34 @@ 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/v1.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.3.0] - 2026-01-09
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Migration helpers that automatically detect and set UUID foreign key types
|
|
12
|
+
- Smart `references` method that inspects database schema to determine primary key types
|
|
13
|
+
- Automatic UUID type assignment for polymorphic associations when using global UUID primary keys
|
|
14
|
+
- Comprehensive test coverage for migration helper functionality
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
- Eliminated need for manual editing of Action Text and Active Storage migrations
|
|
18
|
+
- Updated install generator message to reflect automatic foreign key type handling
|
|
19
|
+
- Updated README.md to document the improved zero-config experience
|
|
20
|
+
- Changed "Zero config after install" status from "Yes (mostly)" to "Yes"
|
|
21
|
+
|
|
22
|
+
### Removed
|
|
23
|
+
- Manual migration editing requirement for Action Text & Active Storage compatibility
|
|
24
|
+
|
|
25
|
+
## [0.2.0] - 2026-01-07
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
- SQLite schema dumping support for UUID primary keys using Ruby format
|
|
29
|
+
- Custom UUID type implementation for ActiveRecord type casting and validation
|
|
30
|
+
- SQLite3 adapter extension for native UUID database type definitions
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
- Switched SQLite schema format from SQL to Ruby for improved compatibility and standard Rails behavior
|
|
34
|
+
- Updated test suite to expect Ruby schema format for SQLite databases
|
|
35
|
+
|
|
8
36
|
## [0.1.0] - 2026-01-07
|
|
9
37
|
|
|
10
38
|
### Added
|
data/README.md
CHANGED
|
@@ -13,6 +13,8 @@ Works great with **PostgreSQL 18+** and **SQLite 3.51+** — zero extra extensio
|
|
|
13
13
|
- Automatically sets `:uuid` as default primary key type
|
|
14
14
|
- Adds reliable `before_create` callback for UUIDv7 generation
|
|
15
15
|
- Works perfectly on **both PostgreSQL 18+** and **SQLite** (and older PostgreSQL versions too)
|
|
16
|
+
- **PostgreSQL**: Uses native `UUID` column types with full database support
|
|
17
|
+
- **SQLite**: Uses `VARCHAR(36)` with custom ActiveRecord type handling
|
|
16
18
|
- Zero database extensions needed
|
|
17
19
|
- Minimal and maintainable — no monkey-patching hell
|
|
18
20
|
|
|
@@ -21,7 +23,7 @@ Works great with **PostgreSQL 18+** and **SQLite 3.51+** — zero extra extensio
|
|
|
21
23
|
Add to your `Gemfile`:
|
|
22
24
|
|
|
23
25
|
```ruby
|
|
24
|
-
gem "rails-uuid-pk", "~> 0.
|
|
26
|
+
gem "rails-uuid-pk", "~> 0.3"
|
|
25
27
|
```
|
|
26
28
|
|
|
27
29
|
Then run:
|
|
@@ -57,8 +59,6 @@ User.create!(name: "Alice") # ← id is automatically a proper UUIDv7
|
|
|
57
59
|
|
|
58
60
|
### Action Text & Active Storage
|
|
59
61
|
|
|
60
|
-
**These Rails engines do NOT automatically respect the `primary_key_type: :uuid` setting** when generating their install migrations.
|
|
61
|
-
|
|
62
62
|
When you run:
|
|
63
63
|
|
|
64
64
|
```bash
|
|
@@ -66,37 +66,25 @@ rails action_text:install
|
|
|
66
66
|
rails active_storage:install
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
```ruby
|
|
72
|
-
t.references :record, null: false, polymorphic: true, index: false
|
|
73
|
-
# to
|
|
74
|
-
t.references :record, null: false, polymorphic: true, index: false, type: :uuid
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
Same applies to `active_storage_attachments.record_id`.
|
|
78
|
-
|
|
79
|
-
**Without this change** you will get:
|
|
69
|
+
The generated migrations will **automatically use the correct foreign key types** when referencing tables with UUID primary keys. No manual editing required!
|
|
80
70
|
|
|
81
|
-
- `
|
|
82
|
-
- Duplicate key violations on uniqueness indexes
|
|
83
|
-
- Association failures
|
|
71
|
+
This works because rails-uuid-pk includes smart migration helpers that detect the primary key type of referenced tables and automatically set `type: :uuid` for foreign keys.
|
|
84
72
|
|
|
85
|
-
|
|
86
|
-
The gem shows a big warning during installation — but double-check every time you install these engines.
|
|
73
|
+
### Polymorphic associations
|
|
87
74
|
|
|
88
|
-
|
|
75
|
+
**Polymorphic associations** (like Action Text's `record` references) will automatically use the correct foreign key type based on the referenced table's primary key. If the parent model uses UUID primary keys, the foreign key will be UUID type.
|
|
89
76
|
|
|
90
|
-
|
|
77
|
+
For **custom polymorphic associations**, the migration helpers will also automatically detect and set the correct type:
|
|
91
78
|
|
|
92
79
|
```ruby
|
|
93
|
-
#
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
has_many :comments, as: :commentable
|
|
80
|
+
# This will automatically use type: :uuid if the parent models have UUID primary keys
|
|
81
|
+
create_table :comments do |t|
|
|
82
|
+
t.references :commentable, polymorphic: true
|
|
83
|
+
end
|
|
98
84
|
```
|
|
99
85
|
|
|
86
|
+
No manual `type: :uuid` specification needed!
|
|
87
|
+
|
|
100
88
|
## Features / Trade-offs
|
|
101
89
|
|
|
102
90
|
| Feature | Status | Notes |
|
|
@@ -105,7 +93,7 @@ has_many :comments, as: :commentable
|
|
|
105
93
|
| PostgreSQL 18+ native `uuidv7()` | Not used | Fallback approach — more universal, no extensions needed |
|
|
106
94
|
| SQLite support | Full | No native function → app-side generation works great |
|
|
107
95
|
| Index locality / performance | Very good | UUIDv7 is monotonic → almost as good as sequential IDs |
|
|
108
|
-
| Zero config after install | Yes
|
|
96
|
+
| Zero config after install | Yes | Migration helpers automatically handle foreign key types |
|
|
109
97
|
| Works with Rails 7.1 – 8+ | Yes | Tested conceptually up to Rails 8.1+ |
|
|
110
98
|
|
|
111
99
|
## Why not use native PostgreSQL `uuidv7()`?
|
|
@@ -13,18 +13,15 @@ module RailsUuidPk
|
|
|
13
13
|
def show_next_steps
|
|
14
14
|
say "\nrails-uuid-pk was successfully installed!", :green
|
|
15
15
|
|
|
16
|
-
say "\n
|
|
16
|
+
say "\n✅ Action Text & Active Storage compatibility", :green
|
|
17
17
|
say "─────────────────────────────────────────────────────────────"
|
|
18
|
-
say "
|
|
18
|
+
say "Migration helpers now automatically handle foreign key types!"
|
|
19
|
+
say "When you run:"
|
|
19
20
|
say " rails action_text:install"
|
|
20
21
|
say " rails active_storage:install"
|
|
21
22
|
say ""
|
|
22
|
-
say "
|
|
23
|
-
say ""
|
|
24
|
-
say " t.references :record, null: false, polymorphic: true, index: false, type: :uuid"
|
|
25
|
-
say ""
|
|
26
|
-
say "Without this change you'll get type mismatch errors (bigint vs uuid)."
|
|
27
|
-
say "This is a Rails limitation - see Rails guides for details."
|
|
23
|
+
say "The generated migrations will automatically use the correct UUID types"
|
|
24
|
+
say "for foreign keys. No manual editing required!"
|
|
28
25
|
say "─────────────────────────────────────────────────────────────\n"
|
|
29
26
|
|
|
30
27
|
say "\nRecommended next steps:", :yellow
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module RailsUuidPk
|
|
2
|
+
module MigrationHelpers
|
|
3
|
+
module References
|
|
4
|
+
def references(*args, **options)
|
|
5
|
+
ref_name = args.first
|
|
6
|
+
ref_table = options.delete(:to_table) || ref_name.to_s.pluralize
|
|
7
|
+
|
|
8
|
+
# Only set UUID type if not already explicitly set by user
|
|
9
|
+
# Rails sets type: :integer by default, so we override that
|
|
10
|
+
# But if user explicitly set a different type, we respect it
|
|
11
|
+
if (uuid_primary_key?(ref_table) || (options[:polymorphic] && application_uses_uuid_primary_keys?)) && options[:type] == :integer
|
|
12
|
+
options[:type] = :uuid
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
super
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def application_uses_uuid_primary_keys?
|
|
19
|
+
# Check if the application is configured to use UUID primary keys globally
|
|
20
|
+
Rails.application.config.generators.options[:active_record]&.[](:primary_key_type) == :uuid
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
alias_method :belongs_to, :references
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def uuid_primary_key?(table_name)
|
|
28
|
+
conn = @conn || @base || (respond_to?(:connection) ? connection : nil)
|
|
29
|
+
return false unless conn&.table_exists?(table_name)
|
|
30
|
+
|
|
31
|
+
pk_column = find_primary_key_column(table_name, conn)
|
|
32
|
+
return false unless pk_column
|
|
33
|
+
|
|
34
|
+
pk_column.sql_type.downcase.match?(/\A(uuid|varchar\(36\))\z/)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def find_primary_key_column(table_name, conn)
|
|
38
|
+
pk_name = conn.primary_key(table_name)
|
|
39
|
+
return nil unless pk_name
|
|
40
|
+
|
|
41
|
+
conn.columns(table_name).find { |c| c.name == pk_name }
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -6,34 +6,50 @@ module RailsUuidPk
|
|
|
6
6
|
end
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
initializer "rails-uuid-pk.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
initializer "rails-uuid-pk.configure_type_map", after: "active_record.initialize_database" do
|
|
10
|
+
ActiveSupport.on_load(:active_record) do
|
|
11
|
+
if ActiveRecord::Base.connection.adapter_name == "SQLite"
|
|
12
|
+
# Register the UUID type with ActiveRecord
|
|
13
|
+
ActiveRecord::Type.register(:uuid, RailsUuidPk::Type::Uuid, adapter: :sqlite3)
|
|
14
|
+
|
|
15
|
+
# Map varchar SQL type to our custom UUID type (since that's how UUID columns are stored in SQLite)
|
|
16
|
+
ActiveRecord::Base.connection.send(:type_map).register_type(/varchar/i) do |sql_type|
|
|
17
|
+
RailsUuidPk::Type::Uuid.new
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Also map "uuid" SQL type to our custom UUID type for direct lookups
|
|
21
|
+
ActiveRecord::Base.connection.send(:type_map).register_type "uuid" do |sql_type|
|
|
22
|
+
RailsUuidPk::Type::Uuid.new
|
|
23
|
+
end
|
|
24
|
+
end
|
|
13
25
|
end
|
|
14
26
|
end
|
|
15
27
|
|
|
28
|
+
initializer "rails-uuid-pk.native_types" do
|
|
29
|
+
require "active_record/connection_adapters/sqlite3_adapter"
|
|
30
|
+
ActiveRecord::ConnectionAdapters::SQLite3Adapter.prepend(RailsUuidPk::Sqlite3AdapterExtension)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
initializer "rails-uuid-pk.schema_format" do |app|
|
|
36
|
+
# Ensure schema_format is set to :ruby for SQLite (default in Rails)
|
|
37
|
+
app.config.active_record.schema_format ||= :ruby
|
|
38
|
+
end
|
|
39
|
+
|
|
16
40
|
initializer "rails-uuid-pk.include_concern" do
|
|
17
41
|
ActiveSupport.on_load(:active_record) do
|
|
18
42
|
ActiveRecord::Base.include RailsUuidPk::HasUuidv7PrimaryKey
|
|
19
43
|
end
|
|
20
44
|
end
|
|
21
45
|
|
|
22
|
-
initializer "rails-uuid-pk.
|
|
46
|
+
initializer "rails-uuid-pk.migration_helpers" do
|
|
23
47
|
ActiveSupport.on_load(:active_record) do
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
end
|
|
30
|
-
end.new
|
|
31
|
-
|
|
32
|
-
# Map 'uuid' SQL type to our custom UUID type
|
|
33
|
-
ActiveRecord::Base.connection.send(:type_map).register_type "uuid" do |sql_type|
|
|
34
|
-
uuid_type
|
|
35
|
-
end
|
|
36
|
-
end
|
|
48
|
+
require "rails_uuid_pk/migration_helpers"
|
|
49
|
+
|
|
50
|
+
# Include migration helpers for all database adapters
|
|
51
|
+
ActiveRecord::ConnectionAdapters::TableDefinition.prepend(RailsUuidPk::MigrationHelpers::References)
|
|
52
|
+
ActiveRecord::ConnectionAdapters::Table.prepend(RailsUuidPk::MigrationHelpers::References)
|
|
37
53
|
end
|
|
38
54
|
end
|
|
39
55
|
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module RailsUuidPk
|
|
2
|
+
module Type
|
|
3
|
+
class Uuid < ActiveRecord::Type::String
|
|
4
|
+
def type
|
|
5
|
+
# Return :string during schema dumping to avoid "Unknown type 'uuid'" errors
|
|
6
|
+
# Return :uuid for normal operation and tests
|
|
7
|
+
if caller.any? { |c| c.include?("schema_dumper") }
|
|
8
|
+
:string
|
|
9
|
+
else
|
|
10
|
+
:uuid
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def deserialize(value)
|
|
15
|
+
return if value.nil?
|
|
16
|
+
cast(value)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def cast(value)
|
|
20
|
+
return if value.nil?
|
|
21
|
+
return value if value.is_a?(String) && valid?(value)
|
|
22
|
+
|
|
23
|
+
if value.respond_to?(:to_s)
|
|
24
|
+
str = value.to_s
|
|
25
|
+
return str if valid?(str)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Allow invalid UUIDs to be stored (for backward compatibility and manual id assignment)
|
|
29
|
+
value.to_s
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def serialize(value)
|
|
33
|
+
cast(value)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def changed_in_place?(raw_old_value, new_value)
|
|
37
|
+
cast(raw_old_value) != cast(new_value)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def valid?(value)
|
|
43
|
+
value.match?(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
data/lib/rails_uuid_pk.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rails-uuid-pk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Joon Lee
|
|
@@ -68,7 +68,10 @@ files:
|
|
|
68
68
|
- lib/generators/rails_uuid_pk/install/templates/has_uuidv7_primary_key.rb
|
|
69
69
|
- lib/rails_uuid_pk.rb
|
|
70
70
|
- lib/rails_uuid_pk/concern.rb
|
|
71
|
+
- lib/rails_uuid_pk/migration_helpers.rb
|
|
71
72
|
- lib/rails_uuid_pk/railtie.rb
|
|
73
|
+
- lib/rails_uuid_pk/sqlite3_adapter_extension.rb
|
|
74
|
+
- lib/rails_uuid_pk/type.rb
|
|
72
75
|
- lib/rails_uuid_pk/version.rb
|
|
73
76
|
- lib/tasks/rails_uuid_pk_tasks.rake
|
|
74
77
|
homepage: https://github.com/seouri/rails-uuid-pk
|