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

Rails 7:如何在事务块外部检查记录是否更新成功

解决方法

可以通过跟踪事务执行状态,结合ActiveRecord内置方法实现需求,以下是修改后的代码:

def update
  transaction_success = false

  ActiveRecord::Base.transaction do
    # 创建或查找地址,确保操作成功
    address = Address.find_or_create_by(address_params)
    unless address.persisted?
      raise ActiveRecord::Rollback
    end

    # 创建或查找发票账户并关联地址
    @invoice_account = InvoiceAccount.find_or_create_by(
      invoice_account_params.merge(invoice_address_id: address.id)
    )
    unless @invoice_account.persisted?
      raise ActiveRecord::Rollback
    end

    # 定位目标发票
    @invoice = Invoice.find_by_id(params[:id])
    unless @invoice
      raise ActiveRecord::Rollback
    end

    # 执行更新并标记结果
    transaction_success = @invoice.update(
      invoice_params.merge(purchaser_id: @invoice_account.id)
    )
    unless transaction_success
      raise ActiveRecord::Rollback
    end
  end

  respond_to do |format|
    if transaction_success && @invoice.persisted?
      format.html { redirect_to invoice_url(@invoice), notice: "发票更新成功。" }
      format.json { render :show, status: :ok, location: @invoice }
    else
      format.html { render :edit, status: :unprocessable_entity }
      format.json { render json: @invoice&.errors || {}, status: :unprocessable_entity }
    end
  end
end

关键点:

  • 事务状态跟踪:用transaction_success变量记录全流程是否成功,任何一步失败就触发回滚。
  • persisted?的用法:检查地址、发票账户是否成功存入数据库——find_or_create_by创建失败(比如验证不通过)时会返回未保存的对象,此时persisted?为false。
  • update的返回值:@invoice.update本身返回布尔值,成功为true,失败(验证不通过等)为false,结合回滚逻辑确保只有全流程无问题才提交事务。
  • 手动回滚:用raise ActiveRecord::Rollback触发事务回滚,这个异常不会向外传播,只会终止当前事务。

要是只想单独确认@invoice是否更新成功,也可以用@invoice.errors.empty?(更新失败时错误信息会存在errors里),但必须结合事务是否提交——因为就算update返回true,事务回滚后数据库里的记录也不会变化。

内容的提问来源于stack exchange,提问作者Michal Hájek

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 23:10:27