Tengo el siguiente código
ActiveRecord::Base.transaction do begin account.save # outer statement begin user.save # inner statement rescue StandardError raise ActiveRecord::Rollback end rescue StandardError raise ActiveRecord::Rollback end endSi hay una excepción en la 'declaración interna', solo se revertirá el 'usuario', ¿verdad? 'cuenta' no se revertirá en ese caso, ¿no es así?
En su código hay una sola transacción de base de datos, y es todo o nada. Revertir una transacción revertirá todos los cambios realizados en esa transacción, independientemente de dónde emita la reversión.
También puede anidar transacciones, pero tenga cuidado de que, de forma predeterminada, las transacciones se agrupan, por lo que incluso si agrega una segunda transacción dentro de la primera transacción:
ActiveRecord::Base.transaction do begin account.save # outer statement ActiveRecord::Base.transaction do begin user.save # inner statement rescue StandardError raise ActiveRecord::Rollback end end rescue StandardError raise ActiveRecord::Rollback end endEsto aún dará como resultado la transacción única, y la reversión cancelará todos los cambios.
Para solicitar una subtransacción real, debe agregar request_new: true a la transacción interna:
ActiveRecord::Base.transaction do begin account.save # outer statement ActiveRecord::Base.transaction(require_new: true) do begin user.save # inner statement rescue StandardError raise ActiveRecord::Rollback end end rescue StandardError raise ActiveRecord::Rollback end endSin embargo , por el momento, la única base de datos que admite transacciones anidadas verdaderas es MS-SQL. Rails en este momento maneja esto usando puntos de guardado, así que no se confunda con los registros.