我遇到了人们双击我的表单提交按钮并提交多次的问题,所以我只想允许一次提交。我的第一个想法是 javascript,但这不是绝对瞬时的,我想要 100% 保证工作的东西。
我的解决方案是使提交具有幂等性,通过给每个表单加载自己的哈希,并在每次提交时检查该哈希是否已经存在,如果存在,则不做任何事情。
所以这是我的代码的要点:
#form
@hash = SecureRandom.urlsafe_base64(20)
f.hidden_field :hash, value: @hash
f.submit "submit"
#controller
existing = Submission.find_by(hash: params[:hash])
if existing.nil?
#enter new Submission into the database with hash: params[:hash]
如果我在提交之间留出一些时间,这会起作用,但是当我双击提交按钮时,两条记录会输入到我的数据库中,具有相同的哈希值。
我在本地主机上使用一个简单的 Puma 3.7 服务器。我的印象是大多数服务器会收到一个请求,执行它,然后继续下一个请求,但这几乎就像是在进行某种类型的并行。
我的问题是:这怎么可能?每个后续记录的 ID 值都比前一个记录大一,因此服务器并不知道前一个记录。那么,如果请求发送得非常快,那么如何忽略唯一哈希要求呢?同样,如果我稍后再尝试使用相同的哈希,则不会发生任何事情,正如预期的那样。