ran*_*guy 3 ruby transactions ruby-on-rails control-flow rails-activerecord
create是一种方法,只有当一切都按预期进行时才应该返回 true,否则返回 false。我要使用错误代码样式的控制流。
class TransferOperator
class TransferError < Struct.new(:type, :message); ; end
attr_reader :transfer, :error
def initialize(transfer)
@transfer = transfer
end
# Creates the transfer and locks money in the bank
def create
return error(:validation_error) if transfer.invalid?
to_bank = transfer.main_to_bank
to_bank.with_lock do
# How does return here behave? Should a raise be issued instead and caught outside?
return error(:insufficient_buffer) if to_bank.available_balance < transfer.amount
to_bank.available_balance -= transfer.amount
to_bank.locked_balance += transfer.amount
to_bank.save!
transfer.save!
end
# Is it guaranteed here that the above transaction has always been succesful?
true
end
private
def error(type, message='')
@error = TransferError.new(type, message)
false
end
end
Run Code Online (Sandbox Code Playgroud)
这里的想法是为调用者提供这样的流程:
def move_money
@transfer = Transfer.new(params)
operator = TransferOperator.new(@transfer)
if operator.create
redirect_to :root, notice: 'success!'
else
if operator.error.type == :validation_error
render action: 'new'
elsif operator.error.type == :insufficient_buffer
redirect_to :root, notice: 'not enough money'
else
# Handle other errors here...
end
end
end
Run Code Online (Sandbox Code Playgroud)
事务中的错误返回会发生什么?
如果返回true,是否保证交易成功?
来自http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html
一个例外是 ActiveRecord::Rollback 异常,它在引发时会触发 ROLLBACK,但不会被事务块重新引发。
Rails 有可能自己提出ActiveRecord::Rollback吗?如果是这样,那么事务将默默地失败并返回 true(这不是我们想要的)。
我相信这在 Rails 7 中已经改变。在撰写本文时,最新版本的 Rails (7.0.2) 将在遇到return.
请参阅https://github.com/rails/rails/issues/45017和早期版本中的弃用警告https://github.com/rails/rails/pull/29333
太长了;如果您需要从当前上下文返回,请不要使用returnuse 。next
如果您嵌套在多个块内并且无法使用next,请将事务的内容提取到其自己的方法中并在那里使用 return 。
如果要使事务回滚,则必须引发错误。你有几个选择:
ActiveRecord::Rollback并且事务将被回滚并且不会在事务块之外重新引发错误。正如您所说,这将默默地回滚事务。可能不是你想要的。返回一个错误对象什么都不做。这只是另一个被传递的对象。
| 归档时间: |
|
| 查看次数: |
7538 次 |
| 最近记录: |