Ruby on rails 如何确保unique id在Rails中确实是唯一的?

Ruby on rails 如何确保unique id在Rails中确实是唯一的?,ruby-on-rails,model,uuid,Ruby On Rails,Model,Uuid,我想将对象的url从/object/123替换为/object/f8a3b2,因此在创建对象时,我不使用id列,而是手动生成uid列 我可以使用可用的uuid库生成uid,但如何确保生成的值始终是唯一的 我在uid列上设置了一个唯一的索引,因此如果它不是唯一的,它应该会抛出一个错误-我可以在模型级别捕获该错误,创建另一个uid,然后重试吗?可能有更好的方法,但是第一件突然出现在我脑海中的事情是,正如你所建议的那样,在活动记录模型上使用验证方法的唯一性 在您的模型中: class MyUnique

我想将对象的url从
/object/123
替换为
/object/f8a3b2
,因此在创建对象时,我不使用
id
列,而是手动生成
uid

我可以使用可用的uuid库生成uid,但如何确保生成的值始终是唯一的


我在uid列上设置了一个唯一的索引,因此如果它不是唯一的,它应该会抛出一个错误-我可以在模型级别捕获该错误,创建另一个uid,然后重试吗?

可能有更好的方法,但是第一件突然出现在我脑海中的事情是,正如你所建议的那样,在活动记录模型上使用
验证
方法的唯一性

在您的模型中:

class MyUniqueModel < ActiveRecord::Base
    validates_uniqueness_of :uuid_column
end

如果您的模型上有其他验证,那么我的建议会导致您遇到的问题是确定保存失败是由您明显不唯一的uuid引起的,还是由其他验证错误引起的。这意味着您必须按失败列过滤循环体,以确定是否需要重新生成另一个UUID。

可能有更好的方法来实现这一点,但我想到的第一件事是在活动记录模型上使用
验证
方法的唯一性,正如你所建议的

在您的模型中:

class MyUniqueModel < ActiveRecord::Base
    validates_uniqueness_of :uuid_column
end
如果您的模型上有其他验证,那么我的建议会导致您遇到的问题是确定保存失败是由您明显不唯一的uuid引起的,还是由其他验证错误引起的。这意味着您必须按失败列筛选循环体,以确定是否需要重新生成另一个UUID。

使用验证唯一性:

class MyModel < ActiveRecord::Base
  validates :id, uniqueness: true
end
classmymodel
使用验证唯一性:

class MyModel < ActiveRecord::Base
  validates :id, uniqueness: true
end
classmymodel
您应该使用

validates :uid, :uniqueness => true
我必须在这个建议中添加一个警告,因为仍然存在这样一种情况,您将从数据库中获得重复uid列值的错误。你可以在中找到更多关于它的信息

为了捕获重复的uid并重试保存,您可以执行以下操作:

model = Model.create(:uid => generate_uid)
if model.errors[:uid].any?
  model.create(:uid => generate_uid)
end
你应该使用

validates :uid, :uniqueness => true
我必须在这个建议中添加一个警告,因为仍然存在这样一种情况,您将从数据库中获得重复uid列值的错误。你可以在中找到更多关于它的信息

为了捕获重复的uid并重试保存,您可以执行以下操作:

model = Model.create(:uid => generate_uid)
if model.errors[:uid].any?
  model.create(:uid => generate_uid)
end
关于uuid gem 如果您正在使用,您不必担心独特性,因为这已经为您解决了。但是,uuid将生成长的128位唯一ID。所以,如果你想要更短的东西,你可能不想用它

如果你的需求很简单,那就简单一点 如果你想要,比如说,8位数的唯一代码也是随机的,你可以在我的cortex项目中看到这样一个系统的实现

这将生成一个8位字母数字代码来表示应用程序中的资源。生成给定代码后,我尝试执行一个
。按代码查找,如果返回
nil
,我知道它没有被使用

在我的特殊情况下,8位字母数字代码给了我一个包含数百万个可能代码的键空间(我忘了有多少)。根据我的应用程序的使用案例,代码冲突的可能性(已使用代码与可用代码的百分比)很小,可能需要为给定资源多次生成新代码

这样做的结果是,需要为给定资源多次生成新代码的情况非常罕见,因此几乎不需要额外的时间

应用程序中的多个应用程序服务器/线程如何? 我的解决方案的一个限制是,如果您有多个应用程序服务器,但只有一个DB服务器,那么在两个独立的应用程序服务器中的任何一个在集中式DB中创建新的资源记录之前,可能会有两个独立的应用程序服务器生成相同的代码。这会造成一种情况,即可能存在代码冲突,并且除了保存到DB的第一条记录之外,所有记录都将被标记为无效(由于代码列上的唯一性约束)。此特定应用程序仅在单个应用程序服务器实例上运行(可能永远也不会运行)。这是一个已知的权衡,我知道,所以我可以冒险

但是,如果我想解决这个问题,我会限制每个应用服务器的随机代码范围,这样它们就不会意外地重叠。例如,假设我生成的随机代码是00000000-9999999之间的8位数字代码。比如说,如果我有三台应用服务器运行这个应用程序,我会简单地将服务器1限制为生成00000000-33333333之间的代码,服务器2到3333333 4-66666666,服务器3到6666666 7-9999999之间的代码。通过这种方式,它们将保证永远不会重叠代码,并且您仍然可以整天生成唯一的随机密钥

如何将给定的服务器限制在给定的范围内有点离题,但一些可用选项包括:

  • 在每个应用服务器内手动设置配置设置。这是手动的(因此很脆弱),但如果你有稳定数量的应用程序服务器不会改变,这可能是好的
  • 让应用程序服务器彼此对话,协商其随机数范围
  • 放弃,认识到这是,你不需要重新创建轮子,只需要使用UUID
  • 考虑使用作为网络服务运行的集中式唯一ID生成器,例如
  • 关于uuid gem 如果您正在使用,您不必担心独特性,因为这已经为您解决了。但是,uuid将生成长的128位唯一ID。所以,如果你想要更短的东西,你可能不想用它

    如果可以的话,一个更简单的方法