ActiveRecord::Base.transaction do Foo.new.bar end Foo.new.baz
Can I determine programmatically from within the bar()
or baz()
methods if a transaction is already taking place? Looking for something that might look like ActiveRecord::Base.within_transaction?
, that would return true
when called from bar()
and false
when called for baz()
.
In case it is relevant, I'm using a mysql database with the mysql2 gem, and am ok with a solution that works only for mysql.
Transactions in ActiveRecordEvery database operation that happens inside that block will be sent to the database as a transaction. If any kind of unhandled error happens inside the block, the transaction will be aborted, and no changes will be made to the DB.
Rails transactions are a way to ensure that a set of database operations will only occur if all of them succeed. Otherwise they will rollback to the previous state of data.
The purpose of this distinction is that with save! , you are able to catch errors in your controller using the standard ruby facilities for doing so, while save enables you to do the same using standard if-clauses.
You can use
ActiveRecord::Base.connection.open_transactions
to see if your method is executed in a transaction.
ActiveRecord::Base.connection.open_transactions == 0
implies that your method is not executed in a transaction. Anything greater than 0 would imply that your method is executed in a transaction. For example ActiveRecord::Base.connection.open_transactions > 0
Update:
from rails documentation
all database statements in the nested transaction block become part of the parent transaction
So number of open transaction will be one even if you are in a nested transaction.
This is what i got in my console
ActiveRecord::Base.transaction do User.first.update_attribute(:first_name, "something") ActiveRecord::Base.transaction do User.first.update_attribute(:last_name, "something") p ActiveRecord::Base.connection.open_transactions end end (0.3ms) BEGIN User Load (0.8ms) SELECT "users".* FROM "users" LIMIT 1 (0.8ms) UPDATE "users" SET "first_name" = 'something', "updated_at" = '2013-11-20 18:33:52.254088' WHERE "users"."id" = 1 User Load (0.5ms) SELECT "users".* FROM "users" LIMIT 1 (0.4ms) UPDATE "users" SET "last_name" = 'something', "updated_at" = '2013-11-20 18:33:52.266976' WHERE "users"."id" = 1 1 (14.2ms) COMMIT => 1
In Rails 6.0 you can use:
ActiveRecord::Base.connection.transaction_open?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With