-
Edouard CHIN authored
- Fix #54830 (This indirectly fix the issue) - ### Problem The `create_or_find_by` method doesn't allow rolling back a transaction. This is a different behaviour than its counterpart method `find_or_create_by`. The reason is because we are in the double transaction edge case and the outer transaction doesn't see the rollback. ### Details ```ruby class User < ApplicationRecord after_save do raise ActiveRecord::Rollback end end User.find_or_create_by(name: "John") => Correctly rolled back User.create_or_find_by(name: "John") => Does not roll back ``` ### Solution We need to be able to know whether the inner transaction succeeded, which is not possible using `.create`, as this method always returns the record (rather than the status of the transaction). https://github.com/rails/rails/blob/1eac7f27748ffa43c5ce91c036c928fc22d4c597/activerecord/lib/active_record/persistence.rb#L39 Using `new` followed by a save is equivalent to `create`, but with `save` we get the transaction return status and we can properly rollback the outer transaction.
Edouard CHIN authored- Fix #54830 (This indirectly fix the issue) - ### Problem The `create_or_find_by` method doesn't allow rolling back a transaction. This is a different behaviour than its counterpart method `find_or_create_by`. The reason is because we are in the double transaction edge case and the outer transaction doesn't see the rollback. ### Details ```ruby class User < ApplicationRecord after_save do raise ActiveRecord::Rollback end end User.find_or_create_by(name: "John") => Correctly rolled back User.create_or_find_by(name: "John") => Does not roll back ``` ### Solution We need to be able to know whether the inner transaction succeeded, which is not possible using `.create`, as this method always returns the record (rather than the status of the transaction). https://github.com/rails/rails/blob/1eac7f27748ffa43c5ce91c036c928fc22d4c597/activerecord/lib/active_record/persistence.rb#L39 Using `new` followed by a save is equivalent to `create`, but with `save` we get the transaction return status and we can properly rollback the outer transaction.
Loading