ActiveRecordのrequires_new, joinable

まとめるとこう。

  • require_new: 親のトランザクションに合流するかを決める
    • true: 合流せず、新しいトランザクションを作る
    • false: 合流する(デフォルトの挙動)
  • joinable: 子のトランザクションが、自身のトランザクションに合流できるかを決める
    • true: 合流できる(デフォルトの挙動)
    • false: 合流できない

参考. Railsで、うっかりトランザクションをネストしたところロールバックされなくなったため、requires_newとjoinableを調べてみた - メモ的な思考的な

Nested transactions support

ドキュメントによると下記の挙動に気をつけてと書いてある。

ActiveRecord::ConnectionAdapters::DatabaseStatements | RailsDoc(β)

下記の場合、first も second もロールバックされず作られる。

Rollback例外はネストしたトランザクションに握りつぶされ、親のトランザクションは通常通りコミットされるため。

ActiveRecord::Base.transaction do
  Post.create(title: 'first')
  ActiveRecord::Base.transaction do
    Post.create(title: 'second')
    raise ActiveRecord::Rollback
  end
end

下記のようにすれば、firstだけ作られ、ネストした second なデータはロールバックされるようになる。

ActiveRecord::Base.transaction do
  Post.create(title: 'first')
  ActiveRecord::Base.transaction(requires_new: true) do
    Post.create(title: 'second')
    raise ActiveRecord::Rollback
  end
end