create
- метод, который должен возвращать true только тогда, когда все прошло как ожидалось, а false - в противном случае. Я иду за потоком управления стилями ошибок.Возвращает внутренние транзакции и ActiveRecord :: Rollback
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
Идея заключается в том, чтобы иметь такой поток для вызывающего абонента:
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
Что происходит с возвратом ошибки внутри транзакции?
Это гарантия того, что транзакция прошла успешно, если возвращается истина?
От http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html
Одним из исключений является ActiveRecord :: Откат исключение, которое будет вызвать ROLLBACK при подъеме, но не может быть повторно поднятый блок на сделки.
Возможно ли, что Rails поднимет ActiveRecord::Rollback
сам по себе? Если это произойдет, транзакция будет терпеть неудачу и вернётся истина (это не то, что мы хотим).
Можно ли рассчитывать на Rails, не поднимая 'ActiveRecord :: Rollback' самостоятельно _inside_ транзакции? – randomguy
Rails никогда не будет поднимать 'ActiveRecord :: Rollback'. Ну, технически Rails использует эту ошибку внутренне, но это не повысит ее в вашем транзакционном блоке. – infused