класс ActiveRecord::Transaction
Class задаёт интерфейс для взаимодействия с текущим состоянием транзакции.
Он может соответствовать реальной транзакции или точке сохранения либо представлять отсутствие транзакции.
Состояние
Транзакция считается завершённой, если она оборачивает реальную транзакцию, которая была зафиксирована или отменена.
Транзакция считается открытой, если она оборачивает реальную транзакцию, которая ещё не завершена.
С другой стороны, транзакция считается закрытой, если она не открыта. То есть если она представляет отсутствие транзакции или оборачивает реальную, но завершённую транзакцию.
Проверить, открыта или закрыта транзакция, можно с помощью предикатов open? и closed?:
if Article.current_transaction.open? # We are inside a real and not finalized transaction. end
Закрытые транзакции также являются blank?.
Callbacks
После обновления состояния базы данных иногда может потребоваться выполнить дополнительную работу или отразить эти изменения во внешней системе, например очистить или обновить кэш:
def publish_article(article) article.update!(published: true) NotificationService.article_published(article) end
Приведённый выше код работает, но у него есть важный недостаток: он перестаёт работать должным образом, если вызывается внутри транзакции, поскольку взаимодействие с внешней системой происходит до сохранения изменений:
Article.transaction do article = create_article(article) publish_article(article) end
Колбэки, предоставляемые ActiveRecord::Transaction, позволяют переписать этот метод так, чтобы он корректно работал с транзакциями:
def publish_article(article)
article.update!(published: true)
Article.current_transaction.after_commit do
NotificationService.article_published(article)
end
end
В приведённом выше примере, если publish_article вызывается внутри транзакции, колбэк будет вызван после успешной фиксации транзакции, а при вызове вне транзакции — немедленно.
Предостережения
При использовании колбэков after_commit важно учитывать, что если колбэк вызовет ошибку, транзакция не будет отменена, поскольку она уже зафиксирована. Использование только этих колбэков для синхронизации состояния между несколькими системами может привести к проблемам согласованности.
Константы
- NULL_TRANSACTION
Открытые методы экземпляра
# File activerecord/lib/active_record/transaction.rb, line 85
def after_commit(&block)
if @internal_transaction.nil?
yield
else
@internal_transaction.after_commit(&block)
end
end Регистрирует блок, который будет вызван после полной фиксации транзакции.
Если сейчас нет открытых транзакций, блок вызывается немедленно, если только транзакция не завершена. В таком случае попытка зарегистрировать колбэк вызывает исключение ActiveRecord::ActiveRecordError.
Если у транзакции есть родительская транзакция, колбэк передаётся родительской транзакции при фиксации текущей транзакции или удаляется при её отмене. Эта операция повторяется до достижения самой внешней транзакции.
Если колбэк вызывает ошибку, транзакция остаётся зафиксированной.
# File activerecord/lib/active_record/transaction.rb, line 104 def after_rollback(&block) @internal_transaction&.after_rollback(&block) end
Регистрирует блок, который будет вызван после отмены транзакции.
Если сейчас нет открытых транзакций, блок не вызывается. Но если транзакция завершена, попытка зарегистрировать колбэк вызывает исключение ActiveRecord::ActiveRecordError.
Если транзакция успешно зафиксирована, но у неё есть родительская транзакция, колбэк автоматически добавляется в родительскую транзакцию.
Если вся цепочка вложенных транзакций успешно зафиксирована, блок никогда не вызывается.
# File activerecord/lib/active_record/transaction.rb, line 114 def closed? @internal_transaction.nil? || @internal_transaction.closed? end
Возвращает true, если транзакция не существует или завершена.
# File activerecord/lib/active_record/transaction.rb, line 109 def open? !closed? end
Возвращает true, если транзакция существует и ещё не завершена.
# File activerecord/lib/active_record/transaction.rb, line 121
def uuid
if @internal_transaction
@uuid ||= Digest::UUID.uuid_v4
end
end Возвращает UUID этой транзакции или nil, если нет открытой транзакции.
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.