UUID 在 Rails + SQLite 中不应该这么难(于是我写了一个 gem)
Source: Dev.to
TL;DR – 在 Rails + SQLite 应用中使用 UUID / ULID
# Gemfile
gem "sqlite_crypto"
# migration
create_table :users, id: :uuid do |t|
t.string :email
t.timestamps
end
就是这么简单。
外键会自动检测,schema.rb 保持干净,一切都能正常工作。
[→ GitHub] | [→ RubyGems]
我遇到的问题
我在构建一个 Rails 8 应用时使用 SQLite 作为生产数据库(得益于新的 WAL‑mode 默认设置、更好的 busy‑handler 处理等)。当我尝试添加 UUID 主键 时,SQLite 的表现与 PostgreSQL 完全不同。
出现的错误
| 问题 | PostgreSQL | SQLite(使用 gem 前) |
|---|---|---|
| 主键声明 | enable_extension 'pgcrypto' → id: :uuid | schema.rb 导出 id: false 并生成一个 string 列 |
| 外键 | 自动检测 UUID 类型 | 创建了 INTEGER 列,导致关联不匹配 |
User.first | 返回时间上最早的记录 | 返回随机的 UUID 排序记录(UUID v4 并非时间可排序) |
| 样板代码 | 无 | 需要大量手动 type: :string, limit: 36 以及自定义生成器 |
编写 gem 之前我必须做的事
-
冗长的迁移语法
create_table :users, id: false do |t| t.string :id, limit: 36, null: false, primary_key: true t.string :email t.timestamps end -
在每个外键上手动指定类型
create_table :api_keys, id: false do |t| t.string :id, limit: 36, null: false, primary_key: true t.references :user, null: false, foreign_key: true, type: :string, limit: 36 end -
在
ApplicationRecord中自定义 UUID 生成class ApplicationRecord # 示例 UUID "550e8400-e29b-41d4-a716-446655440000" end user.tracking_id #=> "01ARZ3NDEKTSV4RRFFQ69G5FAV"
基准测试
如果你感兴趣,我准备了一个专门用于检查每种 ID 类型性能的 spec。可以在自己的机器上运行:
bundle exec rspec --tag performance
注册自定义类型
ActiveRecord::Type.register(:uuid, SqliteCrypto::Type::Uuid, adapter: :sqlite3)
最难的部分是让 schema dumper 输出简洁的 id: :uuid 而不是冗长的列定义。这需要在 Rails 初始化序列的恰当时机 prepend 模块。
CI 矩阵
我的 CI 矩阵会在以下组合下运行测试:
- Ruby 3.1 – 3.4
- Rails 7.1 – 8.1
我发现了一些仅在特定组合下出现的边缘情况——Rails 8.0 的 schema dumper 与 7.2 的行为在细节上有所不同。
安装
# Gemfile
gem "sqlite_crypto"
如果遇到问题,请在 GitHub 上提交 issue。如果它对你的项目有帮助,请 给仓库加星——这能帮助更多人发现这个 gem。
链接
- GitHub 仓库 – https://github.com/yourname/sqlite_crypto
- RubyGems – https://rubygems.org/gems/sqlite_crypto
- 更新日志 – https://github.com/yourname/sqlite_crypto/blob/main/CHANGELOG.md
贡献
如果你一直想为 Ruby 生态系统贡献却还没开始——我鼓励你动手。构建 sqlite_crypto 让我对 Rails 内部机制的了解超过了多年应用开发的积累。社区需要工具,而你可能就是下一个工具的作者。
如果你在 Rails + SQLite 工作流中发现了痛点,欢迎随时与我分享。我真的很想了解在这个 SQLite‑first 新世界里还有哪些难点。
联系方式
正在使用 sqlite_crypto 开发项目吗?我很想听到你的故事。留下评论或在 GitHub 上找我吧。