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/
我有一个控制器,其方法称为 '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/