En fait, c'est exactement comme ça que Transactions imbriquées a été conçu pour. Je cite des documents oracle :
Ainsi, une transaction enfant dans une transaction imbriquée normale n'a pas son mot à dire sur la façon dont lui ou les autres enfants ou parents (transaction plus importante ) pourrait se comporter, autrement qu'en modifiant des données mutuelles ou en échouant pour une exception.
Mais vous pouvez lui accorder (transaction enfant ) une chance de vote très limitée sur son destin en utilisant la sub-transaction
fonctionnalité comme indiqué dans rails docs
en passant requires_new: true
User.transaction do
User.create(username: 'Kotori')
User.transaction(requires_new: true) do
User.create(username: 'Nemu')
raise ActiveRecord::Rollback
end
end
Ce qui, comme le disent les docs :ne crée que 'Kotori'. puisque le puissant enfant 'Nemu' a choisi de mourir en silence.
Plus de détails sur les règles de transaction imbriquées (documentation oracle )
Mise à jour :
Pour mieux comprendre pourquoi rails nested transactions
fonctionne de cette façon, vous devez en savoir un peu plus sur le fonctionnement des transactions imbriquées au niveau de la base de données, je cite de docs API rails
:
Ok, alors la documentation décrit le comportement d'une nested transaction
dans les deux cas mentionnés comme suit :
Dans le cas d'un appel imbriqué, #transaction se comportera comme suit :
-
Le bloc sera exécuté sans rien faire. Toutes les instructions de base de données qui se produisent dans le bloc sont effectivement ajoutées à la transaction de base de données déjà ouverte.
-
Cependant, si :requires_new est défini, le bloc sera enveloppé dans un point de sauvegarde de la base de données agissant comme une sous-transaction.
J'imagine attention, imagine seulement que :
option(1) (sans requirements_new) est là au cas où vous auriez utilisé un SGBD qui prend entièrement en charge les nested transactions
ou vous êtes satisfait du "faux" comportement de nested_attributes
tandis que option(2) est de supporter le savepoint
solution de contournement si vous ne le faites pas.