【问题标题】:RAILS 3 - Transactions in controllersRAILS 3 - 控制器中的事务
【发布时间】:2013-03-27 10:40:22
【问题描述】:

我在控制器中有一个示例动作。

def some_action
 product = Product.new
 product.name = "namepro"
  if product.save
   client.update_attribute(:product_id,product.id)
  end
end

如何为这段代码添加交易?我尝试使用此示例代码:

def some_action
 **transaction do**
  product = Product.new
  product.name = "namepro"
   if product.save
    client.update_attribute(:product_create,Time.now)
   end
 **end**
end

但它会产生这个错误:

undefined method `transaction'

我读到过在控制器中使用事务是一种不好的做法,但我不知道原因是什么 (http://markdaggett.com/blog/2011/12/01/transactions-in-rails/)

在示例中,如果产品已创建并保存并且客户端更新失败...Rails 不能什么都不做。

谢谢。

【问题讨论】:

    标签: ruby-on-rails-3 transactions controller


    【解决方案1】:

    如果你真的想的话,你可以在控制器中使用事务。正如您所指出的,这是一种不好的做法,但如果您想这样做,只需调用 Product.transaction do 而不是 transaction dotransactionActiveRecord::Base 上的类方法,因此您需要在 ActiveRecord 派生类上调用它。您的应用程序中的任何模型类都可以(挑剔的警告:如果您为不同的模型连接到不同的数据库,那可能不是真的......但您可能没有这样做)。

    这是一个不好的做法的原因是它没有根据 MVC 范式正确分离关注点。您的控制器不应该如此关心您的数据持久性实现。更好的方法是向Product 添加一个方法。也许是这样的:

    def save_and_update_create_time
      transaction do
        if save
          client.update_attribute(:product_create, Time.now)
        end
      end
    end
    

    然后,不要在控制器中调用product.save,而是调用product.save_and_update_client_create_time。您可能还需要将client 传递给该方法;从您的代码中不清楚client 的来源。如果它是product 上的一个属性,那么上面的方法应该可以工作。

    还有更好、更多的 Railsy 方法可以做到这一点,特别是如果 product 知道它的 client 而不需要任何控制器数据。然后你可以像这样使用after_save 回调(添加到Product 类):

    after_save :update_client
    
    private
    
    def update_client(product)
      product.client.update_attribute(:product_create, Time.now)
    end
    

    然后每次保存Product 时,关联客户端上的字段都会更新。您可能需要先引入一些代码来检查 client 是否存在。

    使用回调的好处是,除了更简洁的代码外,整个回调链与保存一起在单个事务中运行;您无需手动创建交易。您可以在Rails documentation 中阅读有关回调的更多信息。

    【讨论】:

    • 非常感谢吉姆,你的解释真的帮了我!
    • 如果将事务逻辑放入模型中,那么事务是否会被限制在一个模型中,以不破坏单独关注规则?通常事务跨多个模型的可能性很高,这些模型在数据库级别不一定相互关联。
    • 是的,我对我评论的那个特定方面改变了主意。我确实喜欢将其排除在控制器之外的想法,但多模型交互应该包含在某个地方。也许是另一个类,但在某些情况下,控制器毕竟是正确的地方。
    • 我认为如果您需要跨多个模型生成事务,您需要聚合根模型。 Martin Fowler 在这里写到 martinfowler.com/bliki/DDD_Aggregate.html
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多