Spec-Zone.ru › Ruby on Rails 8.1

класс ActiveRecord::Transaction

Родитель:
Object

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

Открытые методы экземпляра

after_commit () { || ... } Показать исходный код
# 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.

Если у транзакции есть родительская транзакция, колбэк передаётся родительской транзакции при фиксации текущей транзакции или удаляется при её отмене. Эта операция повторяется до достижения самой внешней транзакции.

Если колбэк вызывает ошибку, транзакция остаётся зафиксированной.

after_rollback (&block) Показать исходный код
# File activerecord/lib/active_record/transaction.rb, line 104
def after_rollback(&block)
  @internal_transaction&.after_rollback(&block)
end

Регистрирует блок, который будет вызван после отмены транзакции.

Если сейчас нет открытых транзакций, блок не вызывается. Но если транзакция завершена, попытка зарегистрировать колбэк вызывает исключение ActiveRecord::ActiveRecordError.

Если транзакция успешно зафиксирована, но у неё есть родительская транзакция, колбэк автоматически добавляется в родительскую транзакцию.

Если вся цепочка вложенных транзакций успешно зафиксирована, блок никогда не вызывается.

blank? ()
Псевдоним для: closed?
closed? () Показать исходный код
# File activerecord/lib/active_record/transaction.rb, line 114
def closed?
  @internal_transaction.nil? || @internal_transaction.closed?
end

Возвращает true, если транзакция не существует или завершена.

Также имеет псевдоним: blank?
open? () Показать исходный код
# File activerecord/lib/active_record/transaction.rb, line 109
def open?
  !closed?
end

Возвращает true, если транзакция существует и ещё не завершена.

uuid () Показать исходный код
# 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.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API