Я экспериментировал с этим. Похоже, что если ваше спасение перехватит исключение, которое вызвало бы откат, часть транзакции, которая уже произошла, будет зафиксирована. В моем случае я хочу, чтобы база данных откатилась до того состояния, которое было до начала транзакции, но я все еще хочу обработать исключение.
Я закончил с этим:
self.transaction do
first_operation
begin
operation_that_might_violate_db_constraint
rescue ActiveRecord::RecordNotUnique
#deal with the error
raise ActiveRecord::Rollback #force a rollback
end
end
Часть raise ActiveRecord::Rollback
обеспечивает полное откат транзакции. Без этого изменения из first_operation
в конечном итоге будут зафиксированы.
ActiveRecord :: Rollback - это особый вид исключений, который не всплывает над уровнем транзакции, поэтому вы не получите необработанное исключение, которое отображает страницу ошибки.
Я не уверен, что это золотой стандарт, но похоже, что он работает.