UUID 在 Rails + SQLite 中不应该这么难(于是我写了一个 gem)

发布: (2025年12月22日 GMT+8 20:07)
4 min read
原文: Dev.to

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 完全不同。

出现的错误

问题PostgreSQLSQLite(使用 gem 前)
主键声明enable_extension 'pgcrypto'id: :uuidschema.rb 导出 id: false 并生成一个 string
外键自动检测 UUID 类型创建了 INTEGER 列,导致关联不匹配
User.first返回时间上最早的记录返回随机的 UUID 排序记录(UUID v4 并非时间可排序)
样板代码需要大量手动 type: :string, limit: 36 以及自定义生成器

编写 gem 之前我必须做的事

  1. 冗长的迁移语法

    create_table :users, id: false do |t|
      t.string :id, limit: 36, null: false, primary_key: true
      t.string :email
      t.timestamps
    end
  2. 在每个外键上手动指定类型

    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
  3. 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。

链接

贡献

如果你一直想为 Ruby 生态系统贡献却还没开始——我鼓励你动手。构建 sqlite_crypto 让我对 Rails 内部机制的了解超过了多年应用开发的积累。社区需要工具,而你可能就是下一个工具的作者。

如果你在 Rails + SQLite 工作流中发现了痛点,欢迎随时与我分享。我真的很想了解在这个 SQLite‑first 新世界里还有哪些难点。

联系方式

正在使用 sqlite_crypto 开发项目吗?我很想听到你的故事。留下评论或在 GitHub 上找我吧。

Back to Blog

相关文章

阅读更多 »

Ruby 4.0.0

请提供您希望翻译的具体摘录或摘要文本,我才能为您进行简体中文翻译。