我有一个名为' actions'的控制器。当应用程序进入方法' example_action'时,它实现第一个方法(1)update_user_table,然后(2)另一个update_userdeal_table。 (两者都会读写数据库)
我的问题如下:如果在控制器中间超时,我想避免更新User表(通过方法1)但UserDeal表不是(通过方法2)的情况)即可。在我的应用中,对于移动用户而言,如果他们是在有互联网连接的地铁中,他们就会启动通过&#39; example_action&#39;控制器,成功执行第一种方法(1),但随后他们进入隧道60秒,非常低(<5b /秒)或没有互联网连接,所以出于用户体验的原因,我超时请求并显示给用户& #39;抱歉太久了,再试一次&#39;。 问题是&#34;损坏&#34;已经在数据库中了:) =&gt; (1)已经执行但未执行(2)。如果没有更新Userdeal,那么在我的应用程序中更新User表是完全不可能的(它会产生数据一致性问题......)
我需要两个方法(1)和(2)是相互依赖的&#34;:如果一个不成功,则不应该执行另一个。这是我描述它的最佳方式。
在实践中,由于(1)首先发生,如果(1)失败,则(2)不会被执行。完美。
问题是如果(1)成功并且(2)没有执行。我怎么能对Rails说,如果(2)没有成功执行,那么我不想执行块内的任何事情&#39; example_action&#39; 。< / p>
这可能吗?
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
答案 0 :(得分:1)
如果您使用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
在您的控制器中。但建议将交易放入模型中。
答案 1 :(得分:1)
处理此问题的最佳方法是使用交易。您可以继续在控制器本身中使用事务,但通常认为这是不好的做法。
class DealsController < ApplicationController
def example_action
Deal.transaction do
update_user_table
update_userdeal_table
end
end
end
与其他提到的一样,您可以将方法移动到模型中的常用方法,并使用事务块将其包装。
我找到了关于rails事务的非常好的帖子。 http://markdaggett.com/blog/2011/12/01/transactions-in-rails/