類別
指定用於與目前交易狀態互動的介面。
它可以對應到實際的交易/儲存點,或表示沒有交易。
狀態
當交易封裝一個已提交或回滾的真實交易時,我們說這是一個已完成交易。
如果交易封裝一個尚未完成的真實交易,則該交易為開啟狀態。
另一方面,如果交易未開啟,則該交易為關閉狀態。也就是說,當它表示缺少交易,或封裝一個真實的但已完成的交易時。
您可以使用 open?
和 closed?
謂詞來檢查交易是否已開啟或已關閉。
if Article.current_transaction.open?
# We are inside a real and not finalized transaction.
end
已關閉的交易也是「空白」的。
呼叫回函
在更新資料庫狀態後,您有時可能需要執行一些額外的任務,或在遠端系統中反映這些變更,例如清除或更新快取。
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
呼叫回函時,請務必注意,如果呼叫回函引發錯誤,交易不會回滾,因為它已提交。僅依賴這些方法來同步多個系統間的狀態可能會導致一致性問題。
- A
- B
- C
- O
- U
常數
NULL_TRANSACTION | = | new(nil).freeze |
執行個體公開方法
after_commit(&block) 連結
註冊一個區塊,以便在交易完全提交後呼叫它。
如果目前沒有開啟的交易,區塊會立即呼叫,除非交易已完成,否則嘗試註冊呼叫回函會引發 ActiveRecord::ActiveRecordError
。
如果交易有父交易,呼叫回函會在當前交易提交時轉移到父交易,或在當前交易回滾時丟棄。此操作會反覆進行,直到到達最外層交易。
如果呼叫回函引發錯誤,交易仍會處於提交狀態。
來源:顯示 | 在 GitHub 上
# 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
after_rollback(&block) 連結
註冊一個區塊,以便在交易回滾後呼叫它。
如果目前沒有開啟的交易,不會呼叫該區塊。但如果交易已完成,嘗試註冊呼叫回函會引發 ActiveRecord::ActiveRecordError
。
如果交易已成功提交但有父交易,呼叫回函會自動新增至父交易。
如果嵌套交易的整個鏈條都已成功提交,那麼區塊就永遠不會被呼叫。
如果交易已經完成,嘗試註冊回呼將會引發 ActiveRecord::ActiveRecordError
。
open?() 連結
如果交易存在且尚未完成,則傳回 true。