繁体   English   中英

Rails 3.2 ActiveRecord事务

[英]Rails 3.2 ActiveRecord Transaction

我一直在读,ActiveRecord事务会自动包含保存和销毁操作。 我的问题涉及以下情况。

我有一个库存系统,可以跟踪货件并在创建货件时调整产品的库存量。 当我删除货件时,我已将其编程,然后将装运数量添加回产品的库存量。 此方案适用于用户犯规货物的情况。 然后,删除货件将把装运的物品添加回库存。

我的问题是,当product_shipments循环时,是否有必要提供Product.transaction块,或者我可以省略它,因为destroy方法会自动包装在事务中? 可以像我一样在事务中包装整个循环吗? 如果出现问题,我怎样才能最好地确保所有这些数据库操作都回滚?

def destroy
  @shipment = Shipment.find(params[:id])
  @shipments = @shipment.product_shipments
  Product.transaction do
    @shipments.each do |s|
      @difference = -(s.qty_shipped.to_i)
      Product.update_inventory_quantities(@difference, s.product_id)
    end
  end
  @shipment.destroy
  respond_with @shipment, :location => shipments_url
end

为了详细说明Mischa的建议,ActiveRecord回调将允许您以几种重要方式改进此代码。 首先,它删除了提示您编写此问题的丑陋事务块。 几乎总是,如果你在Rails中看到类似的事务块,你可能做错了什么。 其次,它开始将事情转移到他们关注的地方。 由于事物处于直观的位置并且大部分利用内置的Rails方法,这不仅可以使维护更容易,而且还可以使事情更容易测试。

我怀疑没有针对此应用程序的测试。 当你进行这种调整时,这可能是写一些的好借口。 它开始分解到一些简单的规范可能会走很长的路,而你的应用程序复杂性似乎可能会让你从增加的思想中受益(特别是由于涉及金钱)。

我将对你的对象的关系做出某些假设,并将它们从下面的示例代码中删除,但我想象的是一个包含Shipments,Products和ProductShipments的has_many:through -type情况。

你的控制器,清理:

def destroy
  # note: you may not need the additional scope of @shipment - depending on your view, you may be able to omit the @
  @shipment = Shipment.destroy(params[:id])
  respond_with @shipment, :location => shipments_url
end

您的货件型号:

class Shipment < ActiveRecord::Base

  before_destroy :restore_unshipped_inventory

  def restore_unshipped_inventory
    product_shipments.each(&:restore_unshipped_inventory)
  end

end

您的加入模式:

class ProductShipment < ActiveRecord::Base  

  def restore_unshipped_inventory
    difference = -(s.qty_shipped.to_i)
    Product.update_inventory_quantities(difference, product.id)
  end

end

老实说,我甚至会更进一步,并且使ProductShipment中的restore_unshipped_inventory在product( product.update_inventory_quantities )的实例上运行,即使所有那个实例方法都调用了你在那里的类方法,只是为了进一步隔离不相关的逻辑。

你所做的是对的。 但你需要在交易中添加@ shipment.destroy 因此,如果交易失败,您的货物将不会被销毁。 如果由于某种原因导致u事务失败,则不会触发任何提交,并且您的事务将回滚。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM