rails-uuid-pk 0.2.0 → 0.4.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: 9a1e3ae77afb9d7050fab7a90ea7596b18894cb00006e36e0dd391bc3a1b1194
4
- data.tar.gz: b28a4b0918db5a7285ad8db6af0e0243a862f781c6476daf1954c282b97475ae
3
+ metadata.gz: 3eb01e2f1dc8ef76a90110c9d6ef882f79cfc6584395129046d404f116be94e3
4
+ data.tar.gz: 7aa3b43c50beb54b037428f0abf36f4df642968eb0ba368bfe57328bcea2f8cf
5
5
  SHA512:
6
- metadata.gz: 63f0882a6e7e8f50b35811b81b9efbd75a25ebaa7eadf2b20a75610a14eeb25a4e10635bd39565756d428585609989aabf418dd5486bc361199f49d0fa9eaffb
7
- data.tar.gz: 7055f26c0c87e83e3af48e3cb08b75cc2582af0de4c3c5706af1ca595468bbf77ba4fa3a9eddc2da05c4f471233c5d1d3debfed2cb0e935ecd1679fb41b97d51
6
+ metadata.gz: '09b2676618355ede8b113e7693e8c1673e1f8c32888f0027ab97fd82c81713af5b2f55b995d565f4445465c8c27ce53c4a42fe4f2247017e6c2cf4a0083af9e7'
7
+ data.tar.gz: 967f36d838dfd8e649a8674cce0a29642f39ee0e1a45dc70c4f66a1597abf65591c71cb434d97fb21affccf337337a04f2602e9fe470d43a464f3b5c2eca2298
data/CHANGELOG.md CHANGED
@@ -5,6 +5,47 @@ 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.4.0] - 2026-01-10
9
+
10
+ ### Added
11
+ - **MySQL 8.0+ support**: Full MySQL compatibility with VARCHAR(36) UUID storage
12
+ - MySQL2 adapter extension for native database type mappings
13
+ - MySQL-specific type handling and schema dumping support
14
+ - Comprehensive MySQL test suite with performance and edge case testing
15
+ - CI pipeline support for MySQL 8.0 testing
16
+ - Updated documentation to include MySQL setup and compatibility notes
17
+
18
+ ### Changed
19
+ - Updated project description to reflect support for PostgreSQL, MySQL, and SQLite
20
+ - Enhanced test runner to support all three database adapters
21
+ - Updated development environment setup to include MySQL configuration
22
+ - Expanded database coverage from 2 to 3 major Rails database adapters
23
+
24
+ ### Technical Details
25
+ - Added `lib/rails_uuid_pk/mysql2_adapter_extension.rb` for MySQL adapter integration
26
+ - Extended Railtie with MySQL-specific type mappings and adapter detection
27
+ - Enhanced migration helpers compatibility with MySQL VARCHAR(36) column detection
28
+ - Added MySQL performance testing (bulk operations, concurrent access, memory efficiency)
29
+ - Implemented MySQL edge case testing (long table names, special characters)
30
+ - Updated CI workflow with MySQL 8.0 service configuration
31
+
32
+ ## [0.3.0] - 2026-01-09
33
+
34
+ ### Added
35
+ - Migration helpers that automatically detect and set UUID foreign key types
36
+ - Smart `references` method that inspects database schema to determine primary key types
37
+ - Automatic UUID type assignment for polymorphic associations when using global UUID primary keys
38
+ - Comprehensive test coverage for migration helper functionality
39
+
40
+ ### Changed
41
+ - Eliminated need for manual editing of Action Text and Active Storage migrations
42
+ - Updated install generator message to reflect automatic foreign key type handling
43
+ - Updated README.md to document the improved zero-config experience
44
+ - Changed "Zero config after install" status from "Yes (mostly)" to "Yes"
45
+
46
+ ### Removed
47
+ - Manual migration editing requirement for Action Text & Active Storage compatibility
48
+
8
49
  ## [0.2.0] - 2026-01-07
9
50
 
10
51
  ### Added
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # rails-uuid-pk
2
2
 
3
3
  **Dead-simple UUIDv7 primary keys for modern Rails apps**
4
- Works great with **PostgreSQL 18+** and **SQLite 3.51+** — zero extra extensions required.
4
+ Works great with **PostgreSQL 18+**, **MySQL 8.0+**, and **SQLite 3.51+** — zero extra extensions required.
5
5
 
6
6
  [![Gem Version](https://img.shields.io/gem/v/rails-uuid-pk.svg?style=flat-square)](https://rubygems.org/gems/rails-uuid-pk)
7
7
  [![Ruby](https://img.shields.io/badge/ruby-≥3.3-red.svg?style=flat-square)](https://www.ruby-lang.org)
@@ -12,7 +12,10 @@ Works great with **PostgreSQL 18+** and **SQLite 3.51+** — zero extra extensio
12
12
  - Uses **native** `SecureRandom.uuid_v7` (Ruby 3.3+)
13
13
  - Automatically sets `:uuid` as default primary key type
14
14
  - Adds reliable `before_create` callback for UUIDv7 generation
15
- - Works perfectly on **both PostgreSQL 18+** and **SQLite** (and older PostgreSQL versions too)
15
+ - Works perfectly on **PostgreSQL 18+**, **MySQL 8.0+**, and **SQLite** (and older versions too)
16
+ - **PostgreSQL**: Uses native `UUID` column types with full database support
17
+ - **MySQL**: Uses `VARCHAR(36)` with custom ActiveRecord type handling
18
+ - **SQLite**: Uses `VARCHAR(36)` with custom ActiveRecord type handling
16
19
  - Zero database extensions needed
17
20
  - Minimal and maintainable — no monkey-patching hell
18
21
 
@@ -21,7 +24,7 @@ Works great with **PostgreSQL 18+** and **SQLite 3.51+** — zero extra extensio
21
24
  Add to your `Gemfile`:
22
25
 
23
26
  ```ruby
24
- gem "rails-uuid-pk", "~> 0.1"
27
+ gem "rails-uuid-pk", "~> 0.3"
25
28
  ```
26
29
 
27
30
  Then run:
@@ -57,8 +60,6 @@ User.create!(name: "Alice") # ← id is automatically a proper UUIDv7
57
60
 
58
61
  ### Action Text & Active Storage
59
62
 
60
- **These Rails engines do NOT automatically respect the `primary_key_type: :uuid` setting** when generating their install migrations.
61
-
62
63
  When you run:
63
64
 
64
65
  ```bash
@@ -66,46 +67,36 @@ rails action_text:install
66
67
  rails active_storage:install
67
68
  ```
68
69
 
69
- You **MUST** manually edit the generated migration and change:
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:
70
+ The generated migrations will **automatically use the correct foreign key types** when referencing tables with UUID primary keys. No manual editing required!
80
71
 
81
- - `PG::DatatypeMismatch` errors
82
- - Duplicate key violations on uniqueness indexes
83
- - Association failures
72
+ 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
73
 
85
- This is a **long-standing Rails limitation** (still present in Rails 8+).
86
- The gem shows a big warning during installation — but double-check every time you install these engines.
74
+ ### Polymorphic associations
87
75
 
88
- ### Other polymorphic associations
76
+ **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
77
 
90
- Any **custom polymorphic** association you create manually should also explicitly use `type: :uuid` if the parent models use UUID primary keys.
78
+ For **custom polymorphic associations**, the migration helpers will also automatically detect and set the correct type:
91
79
 
92
80
  ```ruby
93
- # Good
94
- has_many :comments, as: :commentable, foreign_key: { type: :uuid }
95
-
96
- # Risky (may cause type mismatch)
97
- has_many :comments, as: :commentable
81
+ # This will automatically use type: :uuid if the parent models have UUID primary keys
82
+ create_table :comments do |t|
83
+ t.references :commentable, polymorphic: true
84
+ end
98
85
  ```
99
86
 
87
+ No manual `type: :uuid` specification needed!
88
+
100
89
  ## Features / Trade-offs
101
90
 
102
91
  | Feature | Status | Notes |
103
92
  |--------------------------------------|-----------------|-----------------------------------------------------------------------|
104
93
  | UUIDv7 generation | Automatic | Uses `SecureRandom.uuid_v7` (very good randomness + monotonicity) |
105
94
  | PostgreSQL 18+ native `uuidv7()` | Not used | Fallback approach — more universal, no extensions needed |
106
- | SQLite support | Full | No native function app-side generation works great |
95
+ | PostgreSQL support | Full | Native `UUID` column types with full database support |
96
+ | MySQL 8.0+ support | Full | Uses `VARCHAR(36)` with custom ActiveRecord type handling |
97
+ | SQLite support | Full | Uses `VARCHAR(36)` with custom ActiveRecord type handling |
107
98
  | Index locality / performance | Very good | UUIDv7 is monotonic → almost as good as sequential IDs |
108
- | Zero config after install | Yes (mostly) | Except Action Text / Active Storage migrations |
99
+ | Zero config after install | Yes | Migration helpers automatically handle foreign key types |
109
100
  | Works with Rails 7.1 – 8+ | Yes | Tested conceptually up to Rails 8.1+ |
110
101
 
111
102
  ## Why not use native PostgreSQL `uuidv7()`?
@@ -131,15 +122,16 @@ This project includes a devcontainer configuration for VS Code. To get started:
131
122
 
132
123
  ### Running Tests
133
124
 
134
- The project includes a comprehensive test suite that runs against both SQLite and PostgreSQL.
125
+ The project includes a comprehensive test suite that runs against SQLite, PostgreSQL, and MySQL.
135
126
 
136
127
  ```bash
137
- # Run all tests (SQLite + PostgreSQL)
128
+ # Run all tests (SQLite + PostgreSQL + MySQL)
138
129
  ./bin/test
139
130
 
140
131
  # Run tests for specific database
141
132
  DB=sqlite ./bin/test # SQLite only
142
133
  DB=postgres ./bin/test # PostgreSQL only
134
+ DB=mysql ./bin/test # MySQL only
143
135
  ```
144
136
 
145
137
  ### Code Quality
@@ -164,9 +156,10 @@ gem install rails-uuid-pk-0.1.0.gem
164
156
 
165
157
  ### Database Setup
166
158
 
167
- For PostgreSQL testing, ensure PostgreSQL is running and accessible. The test suite uses these environment variables:
159
+ For database testing, ensure the respective databases are running and accessible. The test suite uses these environment variables:
168
160
  - `DB_HOST` (defaults to localhost)
169
161
  - `RAILS_ENV=test_postgresql` for PostgreSQL tests
162
+ - `RAILS_ENV=test_mysql` for MySQL tests
170
163
 
171
164
  ## Contributing
172
165
 
@@ -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⚠️ IMPORTANT - Action Text & Active Storage compatibility", :red
16
+ say "\n Action Text & Active Storage compatibility", :green
17
17
  say "─────────────────────────────────────────────────────────────"
18
- say "When you run any of these commands:"
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 "You **MUST** manually edit the generated migration and add:"
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
@@ -0,0 +1,9 @@
1
+ module RailsUuidPk
2
+ module Mysql2AdapterExtension
3
+ def native_database_types
4
+ super.merge(
5
+ uuid: { name: "varchar", limit: 36 }
6
+ )
7
+ end
8
+ end
9
+ end
@@ -17,6 +17,19 @@ module RailsUuidPk
17
17
  RailsUuidPk::Type::Uuid.new
18
18
  end
19
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
+ elsif ActiveRecord::Base.connection.adapter_name == "MySQL"
25
+ # Register the UUID type with ActiveRecord for MySQL
26
+ ActiveRecord::Type.register(:uuid, RailsUuidPk::Type::Uuid, adapter: :mysql2)
27
+
28
+ # Map varchar SQL type to our custom UUID type (since that's how UUID columns are stored in MySQL)
29
+ ActiveRecord::Base.connection.send(:type_map).register_type(/varchar/i) do |sql_type|
30
+ RailsUuidPk::Type::Uuid.new
31
+ end
32
+
20
33
  # Also map "uuid" SQL type to our custom UUID type for direct lookups
21
34
  ActiveRecord::Base.connection.send(:type_map).register_type "uuid" do |sql_type|
22
35
  RailsUuidPk::Type::Uuid.new
@@ -30,6 +43,15 @@ module RailsUuidPk
30
43
  ActiveRecord::ConnectionAdapters::SQLite3Adapter.prepend(RailsUuidPk::Sqlite3AdapterExtension)
31
44
  end
32
45
 
46
+ initializer "rails-uuid-pk.mysql_native_types" do
47
+ begin
48
+ require "active_record/connection_adapters/mysql2_adapter"
49
+ ActiveRecord::ConnectionAdapters::Mysql2Adapter.prepend(RailsUuidPk::Mysql2AdapterExtension)
50
+ rescue LoadError
51
+ # MySQL adapter not available, skip MySQL-specific initialization
52
+ end
53
+ end
54
+
33
55
 
34
56
 
35
57
  initializer "rails-uuid-pk.schema_format" do |app|
@@ -42,5 +64,15 @@ module RailsUuidPk
42
64
  ActiveRecord::Base.include RailsUuidPk::HasUuidv7PrimaryKey
43
65
  end
44
66
  end
67
+
68
+ initializer "rails-uuid-pk.migration_helpers" do
69
+ ActiveSupport.on_load(:active_record) do
70
+ require "rails_uuid_pk/migration_helpers"
71
+
72
+ # Include migration helpers for all database adapters
73
+ ActiveRecord::ConnectionAdapters::TableDefinition.prepend(RailsUuidPk::MigrationHelpers::References)
74
+ ActiveRecord::ConnectionAdapters::Table.prepend(RailsUuidPk::MigrationHelpers::References)
75
+ end
76
+ end
45
77
  end
46
78
  end
@@ -1,3 +1,3 @@
1
1
  module RailsUuidPk
2
- VERSION = "0.2.0"
2
+ VERSION = "0.4.0"
3
3
  end
data/lib/rails_uuid_pk.rb CHANGED
@@ -2,6 +2,7 @@ require "rails_uuid_pk/version"
2
2
  require "rails_uuid_pk/concern"
3
3
  require "rails_uuid_pk/type"
4
4
  require "rails_uuid_pk/sqlite3_adapter_extension"
5
+ require "rails_uuid_pk/mysql2_adapter_extension"
5
6
  require "rails_uuid_pk/railtie"
6
7
 
7
8
  module RailsUuidPk
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.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joon Lee
@@ -23,6 +23,20 @@ dependencies:
23
23
  - - "~>"
24
24
  - !ruby/object:Gem::Version
25
25
  version: '8.0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: mysql2
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: 0.5.7
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 0.5.7
26
40
  - !ruby/object:Gem::Dependency
27
41
  name: pg
28
42
  requirement: !ruby/object:Gem::Requirement
@@ -51,8 +65,8 @@ dependencies:
51
65
  - - "~>"
52
66
  - !ruby/object:Gem::Version
53
67
  version: 2.9.0
54
- description: Automatically use UUIDv7 for all primary keys in Rails applications.
55
- Works with PostgreSQL and SQLite, zero configuration required.
68
+ description: Automatically use UUID v7 for all primary keys in Rails applications.
69
+ Works with PostgreSQL, MySQL, and SQLite, zero configuration required.
56
70
  email:
57
71
  - seouri@gmail.com
58
72
  executables: []
@@ -68,6 +82,8 @@ files:
68
82
  - lib/generators/rails_uuid_pk/install/templates/has_uuidv7_primary_key.rb
69
83
  - lib/rails_uuid_pk.rb
70
84
  - lib/rails_uuid_pk/concern.rb
85
+ - lib/rails_uuid_pk/migration_helpers.rb
86
+ - lib/rails_uuid_pk/mysql2_adapter_extension.rb
71
87
  - lib/rails_uuid_pk/railtie.rb
72
88
  - lib/rails_uuid_pk/sqlite3_adapter_extension.rb
73
89
  - lib/rails_uuid_pk/type.rb
@@ -96,5 +112,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
96
112
  requirements: []
97
113
  rubygems_version: 4.0.3
98
114
  specification_version: 4
99
- summary: Dead-simple UUIDv7 primary keys for Rails apps
115
+ summary: Dead-simple UUID v7 primary keys for Rails apps
100
116
  test_files: []