- Jun 2020
transaction calls can be nested. By default, this makes all database statements in the nested transaction block become part of the parent transaction. For example, the following behavior may be surprising: User.transaction do User.create(username: 'Kotori') User.transaction do User.create(username: 'Nemu') raise ActiveRecord::Rollback end end creates both “Kotori” and “Nemu”. Reason is the ActiveRecord::Rollback exception in the nested block does not issue a ROLLBACK. Since these exceptions are captured in transaction blocks, the parent block does not see it and the real transaction is committed.
How is this okay??
When would it ever be the desired/intended behavior for a
raise ActiveRecord::Rollbackto have absolutely no effect? What good is the transaction then??
What happened to the principle of least surprise?
Is there any reason we shouldn't just always use
If, like they say, the inner transaction "become[s] part of the parent transaction", then if anything, it should roll back the parent transaction too — not roll back nothing.
One workaround is to begin a transaction on each class whose models you alter:
- Apr 2020