Ruby on Rails,如何每天重置计数器?

时间:2018-08-21 20:28:07

标签: ruby-on-rails ruby web

每次保存某个模型的记录时,我都需要保存一个参考号,该参考号应由10个数字组成,前8个数字与创建者ID和日期有关,但后2个数字应与从00开始至99结束的递增数字,此计数应每天重置。

例如:

Records created the same day:
SD01011800
GF01011801
MT01011802
...
GH01011899
------------------------------------------------------------------------------
Records created the next day:
SD02011800
GF02011801
MT02011802
...
GH02011899

前2个字母是姓名的缩写,后2个是当日,下2个当月,下2个当年,下2个递增数字(从0到99,每天重置)

每个参考也必须是唯一的。 我缺少最后两位数字的部分,关于如何授予它的任何想法吗? 感谢您的阅读。

2 个答案:

答案 0 :(得分:1)

  

其中前2个字母是名称的缩写,后2个是当日,下2个当月,下2个当年,后2个递增数字(从0到99,每天重置)。

As folks in the comments have pointed out,这假设每天最多有100个条目,并且在2100年会出现问题。一个问题比另一个问题更为紧迫。也许如果您超过100,就可以开始使用字母了吗?

  

每个参考文献都必须唯一。

对于全局唯一标识符UUID,通常是通用唯一标识符。如果您可以更改此要求,它将既简单(数据库已经支持UUID),也更健壮(UUID不限于每天100个),并且更加安全(它们不会泄漏有关被识别事物的信息)。 / p>


假设您无法更改需求,则可以通过将当天的现有行数相加得出下一个数字。

select count(id)
from stuff
where date(created_at) == date(NOW());

但是,如果两个进程都同时插入新记录并获得相同的下一个编号,则会出现问题。如果您期望每天只使用100个,则可能性很小,但仍然可以实现。

Process 1                   Process 2                  Time

select count(id) ...                                   1
                            select count(id) ...       2
insert into stuff ...                                  3
                            insert into stuff...       4

一笔交易无法挽救您。您可以在整个表上获得排他锁,但这是危险且缓慢的。相反,您可以使用an advisory lock进行此操作。只要确保所有写入新记录的代码都使用相同的咨询锁即可。

Stuff.with_advisory_lock(:new_stuff_record) do
  ...
end

或者,将每日ID存储在列中。添加数据库触发器以在插入时加1。午夜安排的作业将其设置回0。

答案 1 :(得分:1)

我将假设您的班级名为Record,并且它具有名为reference_number的属性。

在这种情况下,您可以使用以下方法来获取最后两位数字。

def fetch_following_two_last_digits
  if Record.last.created_at < Time.current.beginning_of_day
    "00"
  else
    (Record.last.reference_number.last(2).to_i + 1).to_s
  end
end

还要假设您每天从未达到100条记录。否则,您将最后三位数。

相关问题