Иногда один из длинного ряда событий внутри действия контроллера завершается неудачей. Например, кредитная карта обрабатывается, но затем тайм-аут запроса ActiveRecord. Есть ли способ сделать эти звонки обратимыми?
например. с этим действием контроллера:
def process_order
cart = Cart.new(params[:cart])
load_order
response = credit_card.charge
if response
submit_order
order.receipt = Pdf.new(render_to_string(:partial => 'receipt')
order.receipt.pdf.generate
order.receipt.save
render :action => 'finished'
else
order.transaction = response
@message = order.transaction.message
order.transaction.save
render :action => 'charge_failed'
end
end
Я хотел бы иметь возможность поставить вокруг него блок так:
def process_order
transaction
cart = Cart.new(params[:cart])
load_order
response = credit_card.charge
if response
submit_order
order.receipt = Pdf.new(render_to_string(:partial => 'receipt')
order.receipt.pdf.generate
order.receipt.save
render :action => 'finished'
else
order.transaction = response
@message = order.transaction.message
order.transaction.save
render :action => 'charge_failed'
end
rollback
credit_card.cancel_charge
...
end
end
Это просто надуманный пример, и я не совсем уверен, как это будет работать на практике. Обычно происходит то, что мы получаем исключение типа ActiveRecord::StatementInvalid: : execution expired
для строки с submit_order
, а затем мы должны вручную запустить остальные строки, которые должны были быть выполнены.