Ruby on Rails - 生成数据库中不存在的随机数
在我的应用程序中,我有一个Case
模型&用户生成的每种情况都有一个case_number
。Ruby on Rails - 生成数据库中不存在的随机数
case_number
从我的Case
模型生成。目前我创建一个case
后,从我的模型创建一个3位数的随机数。
class Case < ActiveRecord::Base
after_create :random_case_number
private
def random_case_number
random_number = Random.rand(999)
self.update_attributes(case_number: random_number)
end
end
这导致所以一些案件有相同的case_number
。如何从我的模型中生成一个当前未使用的随机数字&如果所有3位数字都被采用,它可以移动到4位数字等等。
要生成一个随机数,并确保该号码不存在于数据库中,我会做这样的事情:
before_create :assign_unique_case_number
validates! :case_number, uniqueness: true
private
CASE_NUMBER_RANGE = (10_000..99_999)
def assign_unique_case_number
self.case_number = loop do
number = rand(CASE_NUMBER_RANGE)
break number unless Case.exists?(case_number: number)
end
end
请注意,更多的情况下,也有在数据库中它可能较长采取找到一个未使用的号码。因此,我建议从一开始就使用更大的数字。更多的数字还有另外一个优点:他们很难猜测应用程序中可能或不可能重要的内容。
此外:Rails不能保证数据库中的唯一性。可能存在导致重复的竞赛条件。避免的唯一途径是唯一索引,在这样的迁移添加到数据库列:
add_index :cases, :case_number, unique: true
感谢@spickermann,像一个魅力:) – Rubioli
一旦所有的案例数量用完,这将永远运行。正如@spickerman解释的那样:这不是有效的,特别是当数据库中有越来越多的案例时。 另外:因为case_number是自动生成的,所以验证不会增加值,它只是通过发出另一个select来确保唯一性(它无法真正确保)已确保唯一的数字,从而减慢速度。 –
首先确保case_number
在一个数据库中的唯一索引。
rails generate migration add_unique_index_to_case_number
编辑生成的迁移有点像这样:
class AddUniqueIndexToCaseNumbers < ActiveRecord::Migration[5.1]
def change
add_index(:cases, :case_number, unique: true)
end
end
(您可能需要丢弃无效(一式两份)的情况下,才能添加这个索引)
这保证没有无效的案件号码可以添加到数据库。
然后我会使用一个序列号而不是随机的。如果最终所有的数字从100到999都被使用了,没有太大意义使它随机(并且3位数字没有太多的熵,所以很容易猜出数字)。插入时选择不存在的“随机”数字也有点麻烦。
rails generate migration add_sequence_to_case_numbers
并再次修改迁移:
class AddSequenceToCaseNumbers < ActiveRecord::Migration[5.1]
def change
execute <<-SQL
CREATE SEQUENCE cases_case_number_seq;
ALTER TABLE cases ALTER COLUMN case_number SET DEFAULT nextval('cases_case_number_seq');
SQL
end
end
为什么要用三个随机数,(当采取一切三位数)切换到四位随机数字?为什么使用顺序ID或从更长的随机数开始?如果猜测一个数字仍然可能,为什么你需要随机性? – spickermann
@spickermann感谢您的评论。我可以使用4位数字,但如上所述当我使用3位数字时,即使这样,一些案例也有相同的'case_number',所以我想确保它们是uniq。随机性是需要的,因为我需要的数字是随机的,所以案件不会从1,2,3,4 ... – Rubioli
恕我直言,使案件号码“随机”,但只有3或数字是一个奇怪的要求。谨慎提供一些细节? –