尝于前文论及雪片之标识,其善也,然需稍事配置,盖因须理"工作者之标识"也。
若欲求简而易行,而得同等之利——安全之URL与迅捷之数据库排序——则当察ULIDs(通用唯一且可字顺排序之标识)。
何不径用UUID乎?
众开发者多弃自增之整数,而择UUID者,盖欲隐其商贾之量也。若君之订单号order/550e8400-e29b...如是,则无人知君有客一,抑或百万。
然UUID有大弊:其全然无序,不可预测也。
将数百万随机UUID插入数据库,则"树索引"渐次崩坏,迟滞难行。尔之数据库必须遍寻硬盘,方得新数据安插之所。
ULID可解此弊。
ULID乃128位(与UUID同),然其首部乃为时戳。此乃ULID之序时也。其独异若UUID,然其序若整数。
今示以四步之法,使ULID行于汝之Rails 8应用。
第一步:安设宝石
吾将用ulid宝石以生字符串。于汝之Gemfile中加此:
gem "ulid"
于终端中运行bundle install。
第二步:ULID之虑
吾欲使添加ULID于任一模型之事极为便捷。此举之良策,乃以Concern为之。此码将确保每创一新记录,必生一ULID而赋之ID。
于app/models/concerns/has_ulid.rb处,创一新文。
# app/models/concerns/has_ulid.rb
module HasUlid
extend ActiveSupport::Concern
included do
# Before we save to the DB, generate the ULID
before_create :set_ulid
end
private
def set_ulid
# ULID.generate creates a string like: 01ARZ3NDEKTSV4RRFFQ69G5FAV
self.id ||= ULID.generate
end
end
第三步:迁跃
新模之造,须告Rails,其id乃string,且当禁其本有之自增之理.
rails g model Product name:string
启迁移之文,如斯修之:
# db/migrate/XXXXXXXXXXXXXX_create_products.rb
class CreateProducts < ActiveRecord::Migration[8.0]
def change
# id: false stops the automatic integer ID
create_table :products, id: false do |t|
# We use string for ULID primary key
t.string :id, primary_key: true
t.string :name
t.timestamps
end
end
end
步四:更化其模
今,但纳吾于步二所书之虑。
# app/models/product.rb
class Product < ApplicationRecord
include HasUlid
end
步五:观其效验
启尔 Rails 之台(bin/rails c(JHSNS_SEG_b35e528b_49__)并创制数物:
Product.create(name: "Laptop")
Product.create(name: "Monitor")
Product.create(name: "Keyboard")
# Check the IDs
Product.pluck(:id)
# => ["01HQV...", "01HQV...", "01HQV..."]
细察之,诸ID皆以同文始,盖同分创也。既可序,犹可运Product.order(:id),自当列于时序之正!
言我何以好ULIDs于Rails
- 性能更优:盖因ID可排序,故PostgreSQL(或SQLite)可将其附于索引之末。此法较随机UUID,于"重写"之应用为快。
- 易读:ULID所用字母表特殊(Crockford's Base32),去易淆之字如"I"、"L"、"O",故用户若须键入,较易辨识。
- 无需设置: 与 Snowflake IDs 不同,尔无需配置服务器 ID 或工作节点。尔但安装此宝石,即可行矣。
大抵如是。此乃微调架构,使尔之应用更显专业,且更具可扩展之能。












