ruby-on-rails - 在范围内生成连续的唯一编号
问题描述
我的数据库中有一个字段来保存一个唯一的数字,添加 created_at 年份的最后两位数字。目前一切正常,除了使用 SecureRandom 方法之外,我正在寻找保存连续数字的选项。IE。1901、1902、1903……
模型
before_create :create_number
def create_number
loop do
self. number = ((created_at + 1.year).strftime("%y")).concat(sprintf '%02d', SecureRandom.random_number(200))
break unless self.class.exists?(:number => number)
end
end
解决方案
关键是使用计数查询获取特定年份的记录计数:
class Thing < ApplicationRecord
before_commit :create_number!, if: -> { number.nil? }
private
def count_records_from_same_year
self.class.where(
created_at: (created_at.beginning_of_year..created_at.end_of_year)
).count
end
def create_number!
loop do
year = (created_at + 1.year).strftime("%y")
self.number = year.concat(sprintf '%02d', count_records_from_same_year)
break unless self.class.where(number: self.number).exists?
end
end
end
如您所见,它会生成连续的数字:
irb(main):001:0> Thing.create
(0.3ms) BEGIN
Thing Create (1.3ms) INSERT INTO "things" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id" [["created_at", "2018-10-12 09:57:24.527527"], ["updated_at", "2018-10-12 09:57:24.527527"]]
(1.2ms) SELECT COUNT(*) FROM "things" WHERE "things"."created_at" BETWEEN $1 AND $2 [["created_at", "2018-01-01 00:00:00"], ["created_at", "2018-12-31 23:59:59.999999"]]
Thing Exists (1.4ms) SELECT 1 AS one FROM "things" WHERE "things"."number" = $1 LIMIT $2 [["number", "1901"], ["LIMIT", 1]]
(0.7ms) COMMIT
=> #<Thing id: 1, number: "1901", created_at: "2018-10-12 09:57:24", updated_at: "2018-10-12 09:57:24">
irb(main):002:0> Thing.create
(0.3ms) BEGIN
Thing Create (0.8ms) INSERT INTO "things" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id" [["created_at", "2018-10-12 09:57:26.402797"], ["updated_at", "2018-10-12 09:57:26.402797"]]
(0.7ms) SELECT COUNT(*) FROM "things" WHERE "things"."created_at" BETWEEN $1 AND $2 [["created_at", "2018-01-01 00:00:00"], ["created_at", "2018-12-31 23:59:59.999999"]]
Thing Exists (0.8ms) SELECT 1 AS one FROM "things" WHERE "things"."number" = $1 LIMIT $2 [["number", "1902"], ["LIMIT", 1]]
(0.7ms) COMMIT
=> #<Thing id: 2, number: "1902", created_at: "2018-10-12 09:57:26", updated_at: "2018-10-12 09:57:26">
irb(main):003:0> Thing.create
(0.5ms) BEGIN
Thing Create (0.7ms) INSERT INTO "things" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id" [["created_at", "2018-10-12 09:57:27.537635"], ["updated_at", "2018-10-12 09:57:27.537635"]]
(1.6ms) SELECT COUNT(*) FROM "things" WHERE "things"."created_at" BETWEEN $1 AND $2 [["created_at", "2018-01-01 00:00:00"], ["created_at", "2018-12-31 23:59:59.999999"]]
Thing Exists (0.6ms) SELECT 1 AS one FROM "things" WHERE "things"."number" = $1 LIMIT $2 [["number", "1903"], ["LIMIT", 1]]
(0.7ms) COMMIT
=> #<Thing id: 3, number: "1903", created_at: "2018-10-12 09:57:27", updated_at: "2018-10-12 09:57:27">
推荐阅读
- apache-camel - 访问骆驼正文内容以动态加载 SQL 语句 - org.apache.camel.RuntimeCamelException
- css - 覆盖字体定义
- bootstrap-4 - 从行中选择一个 div 并以反应形式插入值
- ios - 在 Swift 中,删除 ARSCNView 后如何使内存恢复正常?阿基特
- amazon-web-services - 将单个 Codebuild 项目部署到多个 ECS 容器
- scala - SBT 在 JCenter 上找不到包
- uploading - 在 Open edX 中查询
- c - 运算符 && 和 || 的 C 运算符优先级
- mysql - 带有日期和时间范围的 MySQL 查询问题
- identityserver4 - [身份服务器]: AspNetUserClaims 、 ClientClaims 和 ScopeClaims 有什么区别