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
相关产品推荐
相关产品推荐

