Rails特定模型无记录时意外触发两次create的问题排查求助
排查数据库无记录时两次create触发的问题
嘿,这个问题确实挺诡异的,我之前也碰到过类似的情况,咱们一步步来拆解排查:
先搞清楚核心问题:是一次请求触发两次save,还是两次独立请求?
这是最关键的第一步,直接决定后续排查方向:
- 打开你的Rails服务器日志(
rails server输出的内容),触发一次create操作,仔细看日志里有几个POST /orders请求:- 如果是两个POST请求:那问题出在前端,哪怕你移除了
remote:true,还是有重复提交的情况; - 如果是一个POST请求,但数据库里多了一条记录:那就是后端代码/模型回调里的逻辑导致了两次创建。
- 如果是两个POST请求:那问题出在前端,哪怕你移除了
针对两种情况的具体排查步骤
情况1:两个POST请求(前端问题)
哪怕移除了remote:true,还是可能出现重复提交:
- 检查表单:有没有两个
<input type="submit">按钮?或者表单被嵌套了(一个表单里套另一个表单)?点击提交时会触发两个表单的提交; - 检查自定义JS:有没有自己写的表单提交监听?比如:
这种情况会导致默认表单提交和**JS里的逻辑(如果有AJAX的话)**同时触发,产生两次请求;$('form#order_form').on('submit', function() { // 这里做了一些操作,但没阻止默认提交行为 }); - 检查浏览器自动重试:如果第一次请求返回了5xx错误,某些浏览器会自动重试请求,导致两次create。
情况2:一个请求触发两次save(后端问题)
结合你给出的控制器代码片段,重点排查这几个点:
- 检查
Order模型的回调:有没有after_save、before_save、after_create这类回调里,不小心调用了save、create或者其他会生成新订单的方法?比如:
这种回调会在class Order < ApplicationRecord after_save :create_duplicate_order def create_duplicate_order # 这里不小心创建了新订单 self.class.create(user_id: user_id, ...) end end@sell.save时触发,额外生成一条记录; - 检查控制器里的代码:你同时构建了
@sell和@buy两个订单对象,虽然只写了@sell.save,但有没有可能@buy被其他逻辑意外保存了?比如notify_order方法里有没有操作@buy或者调用了保存逻辑? - 检查
@sell.update的影响:你在@sell.save之后调用了@sell.update(...),如果update触发了某些回调,会不会导致额外的创建操作? - 简化代码测试:把create方法暂时改成最简化的版本:
测试还会不会出现两次创建,如果不会,再逐步加回def create @sell = current_user.orders.build(sell_params) if @sell.save flash[:success] = 'your order has successfully submitted.' redirect_to some_path else render :new end endnotify_order、@sell.update等代码,看加到哪一步问题重现,就能精准定位到问题代码块。
额外小技巧
可以在Order模型里加一个临时的日志输出,看看每次创建时的调用栈:
class Order < ApplicationRecord after_create :log_create_callstack def log_create_callstack Rails.logger.debug "Order created! Callstack:\n#{caller.join("\n")}" end end
这样从日志里就能看到每次创建是被哪段代码触发的,很容易找到重复创建的根源。
内容的提问来源于stack exchange,提问作者Ryu Nishida
相关产品推荐
相关产品推荐

