Module: AfterCommitEverywhere
- Defined in:
- lib/after_commit_everywhere.rb,
lib/after_commit_everywhere/wrap.rb,
lib/after_commit_everywhere/version.rb
Overview
Module allowing to use ActiveRecord transactional callbacks outside of ActiveRecord models, literally everywhere in your application.
Include it to your classes (e.g. your base service object class or whatever)
Defined Under Namespace
Classes: NotInTransaction, Wrap
Constant Summary collapse
- VERSION =
"0.1.5"
Class Method Summary collapse
-
.in_transaction?(connection = ActiveRecord::Base.connection) ⇒ Boolean
Helper method to determine whether we’re currently in transaction or not.
- .register_callback(connection:, name:, no_tx_action:, callback:) ⇒ Object
Instance Method Summary collapse
-
#after_commit(connection: ActiveRecord::Base.connection, &callback) ⇒ Object
Runs
callback
after successful commit of outermost transaction for databaseconnection
. -
#after_rollback(connection: ActiveRecord::Base.connection, &callback) ⇒ Object
Runs
callback
after rolling back of transaction or savepoint (if declared in nested transaction) for databaseconnection
. -
#before_commit(connection: ActiveRecord::Base.connection, &callback) ⇒ Object
Runs
callback
before committing of outermost transaction forconnection
.
Class Method Details
.in_transaction?(connection = ActiveRecord::Base.connection) ⇒ Boolean
Helper method to determine whether we’re currently in transaction or not
93 94 95 96 |
# File 'lib/after_commit_everywhere.rb', line 93 def in_transaction?(connection = ActiveRecord::Base.connection) # service transactions (tests and database_cleaner) are not joinable connection.transaction_open? && connection.current_transaction.joinable? end |
.register_callback(connection:, name:, no_tx_action:, callback:) ⇒ Object
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/after_commit_everywhere.rb', line 74 def register_callback(connection:, name:, no_tx_action:, callback:) raise ArgumentError, "Provide callback to #{name}" unless callback unless in_transaction?(connection) case no_tx_action when :warn_and_execute warn "#{name}: No transaction open. Executing callback immediately." return callback.call when :execute return callback.call when :exception raise NotInTransaction, "#{name} is useless outside transaction" end end wrap = Wrap.new(connection: connection, "#{name}": callback) connection.add_transaction_record(wrap) end |
Instance Method Details
#after_commit(connection: ActiveRecord::Base.connection, &callback) ⇒ Object
Runs callback
after successful commit of outermost transaction for database connection
.
If called outside transaction it will execute callback immediately.
23 24 25 26 27 28 29 30 |
# File 'lib/after_commit_everywhere.rb', line 23 def after_commit(connection: ActiveRecord::Base.connection, &callback) AfterCommitEverywhere.register_callback( connection: connection, name: __method__, callback: callback, no_tx_action: :execute, ) end |
#after_rollback(connection: ActiveRecord::Base.connection, &callback) ⇒ Object
Runs callback
after rolling back of transaction or savepoint (if declared in nested transaction) for database connection
.
Caveat: do not raise ActivRecord::Rollback
in nested transaction block! See api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html#module-ActiveRecord::Transactions::ClassMethods-label-Nested+transactions
64 65 66 67 68 69 70 71 |
# File 'lib/after_commit_everywhere.rb', line 64 def after_rollback(connection: ActiveRecord::Base.connection, &callback) AfterCommitEverywhere.register_callback( connection: connection, name: __method__, callback: callback, no_tx_action: :exception, ) end |
#before_commit(connection: ActiveRecord::Base.connection, &callback) ⇒ Object
Runs callback
before committing of outermost transaction for connection
.
If called outside transaction it will execute callback immediately.
Available only since Ruby on Rails 5.0. See github.com/rails/rails/pull/18936
41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/after_commit_everywhere.rb', line 41 def before_commit(connection: ActiveRecord::Base.connection, &callback) if ActiveRecord::VERSION::MAJOR < 5 raise NotImplementedError, "#{__method__} works only with Rails 5.0+" end AfterCommitEverywhere.register_callback( connection: connection, name: __method__, callback: callback, no_tx_action: :warn_and_execute, ) end |