在我的应用程序中,我有Case
模型&用户生成的每个案例都有case_number
。
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
。我怎样才能从我的模型中生成一个当前未使用的随机数&amp;如果所有3位数字都被采用,它可以移动到4位数,依此类推。
答案 0 :(得分:1)
首先确保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
(您可能需要删除无效(重复)案例才能添加此索引)
这可确保不会向DB添加无效的案例编号。
然后我使用序列号而不是随机序列号。如果最终使用100 - 999的所有数字,那么使其随机化没有多大意义(并且3位数中没有太多熵,因此很容易猜出数字)。选择一个不存在的&#34;随机&#34;也有点麻烦。插入时的数字。
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
答案 1 :(得分:0)
要生成随机数并确保数据库中不存在该数字,我会这样做:
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