You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails事务中Earning创建失败时,新创建Employee未回滚问题

解决方案

首先修正两处关键问题,确保事务能正确回滚新创建的Employee:

1. 修正find_or_create_by的参数传递

原代码中Employee.find_or_create_by(earning_data['external_ref'])的写法错误,find_or_create_by需要接收键值对哈希指定查询条件,正确写法需明确external_ref字段:

employee = Employee.find_or_create_by(external_ref: earning_data['external_ref'])

2. 使用create!触发事务回滚

原代码用Earning.create创建记录时,验证失败仅返回无效对象,不会抛出异常,导致事务正常提交,新创建的Employee被保留。改用create!方法,验证失败时会抛出ActiveRecord::RecordInvalid异常,触发事务回滚,撤销Employee的创建操作。

完整修正后的代码:

data = CSV.read(@file_path, headers: true)
data.each do |earning_data|
  ActiveRecord::Base.transaction do
    # 正确指定员工查询条件
    employee = Employee.find_or_create_by(external_ref: earning_data['external_ref'])
    # 使用create!抛出异常触发事务回滚
    Earning.create!(
      employee: employee,
      earning_date: earning_data['earning_date'],
      amount: earning_data['amount']
    )
  rescue ActiveRecord::RecordInvalid => e
    # 可在此记录错误日志,例如:
    # Rails.logger.error "处理CSV行失败: #{earning_data.to_h}, 错误: #{e.message}"
    next # 跳过当前失败行,继续处理后续数据
  end
end

原理说明

  • 事务的原子性特性:只有事务内所有操作都成功时,才会提交到数据库;任意操作抛出异常,事务会回滚所有未提交的变更。
  • find_or_create_by在事务内执行时,若创建了新的Employee,该记录处于事务未提交状态;当Earning.create!抛出异常时,整个事务回滚,新创建的Employee会被撤销。
  • 已存在的Employee不受影响,因为find_or_create_by仅执行查询操作,无修改或创建行为,回滚不会对其产生变化。

内容的提问来源于stack exchange,提问作者jl118

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 00:45:02