Rails controller - 仅当内部的两个方法成功时才执行操作(相互依赖的方法)

Rails controller - execute action only if the two methods inside succeed (mutually dependent methods)

我有一个控制器,其方法称为 'actions'。当应用进入方法 'example_action' 内部时,它会实现第一个方法 (1) update_user_table,然后 (2) 另一个 update_userdeal_table。 (两者都会读写数据库)

我的问题如下:如果控制器中间超时,我想避免用户 table(通过方法 1)更新但UserDeal table 不是(通过方法 2)。在我的应用程序中,对于移动用户,如果他们在有互联网连接的地铁中,他们会启动通过 'example_action' 控制器的请求,成功执行第一种方法 (1),但随后他们进入隧道 60 秒非常非常低(<5b/秒)或没有互联网连接,因此出于用户体验的原因,我将请求超时并显示给用户 'sorry too long, try again'。 问题是 "damage" 已经在数据库中了:) => (1) 已经执行但没有执行 (2)。在我的应用程序中,如果 Userdeal 未更新,则更新用户 table 是完全不可能的(这会造成数据一致性问题...)

我需要(1)和(2)这两个方法"mutually dependent":一个不成功,另一个就不要执行了。这是我能描述的最好的方式。

实际上,由于 (1) 先发生,如果 (1) 失败,则 (2) 不会执行。完美。

问题是如果(1)成功而(2)没有执行。我怎么说Rails,如果(2)没有执行成功,那我不想执行块'example_action'中的任何东西.

这可能吗?

class DealsController < ApplicationController
  def example_action
    update_user_table
    update_userdeal_table   
  end

  private
  def update_user_table
    # update the table User so it needs to connect to internet and acces the distant User table
  end
  def update_userdeal_table
    # update the table UserDeal table so it needs to connect to internet and access the distant UserDeal table
  end
end

如果您正在使用 ActiveRecord,您可以将您的方法移动到模型中并在 transaction 块中执行它们。

class DealsController < ApplicationController
  def example_action
      // 'user' would have to be defined, or you could work with it as a class method in some way
      user.make_the_deal
  end
end

class User < ActiveRecord::Base
  def make_the_deal
    transaction do
      update_user_table
      update_userdeal_table
    end
  end

  def update_user_table
  end

  def update_userdeal_table
  end
end

您不一定非得输入模型才能执行此操作,您可以这样做:

User.transaction do
  update_user_table
  update_userdeal_table
end

在你的控制器中。但建议将交易放入模型中。

处理这个问题的最好方法是使用事务。您可以继续在控制器本身中使用事务,但通常认为这是不好的做法。

class DealsController < ApplicationController
  def example_action
    Deal.transaction do
      update_user_table
      update_userdeal_table   
    end
  end
end

所以像其他人提到的那样,您可以将这些方法移动到模型中的通用方法并用事务块包装它。

我发现了一笔非常好的 post 关于 rails 的交易。 http://markdaggett.com/blog/2011/12/01/transactions-in-rails/