diff options
author | Ryuta Kamizono <kamipo@gmail.com> | 2018-05-19 11:46:03 +0900 |
---|---|---|
committer | Ryuta Kamizono <kamipo@gmail.com> | 2019-04-16 12:30:45 +0900 |
commit | 63ff495bdf90e0ab20114a49db5cffe3cb9ef2fd (patch) | |
tree | 33d5e390a602ef7c77a2c675865b573802fdd35b /activerecord/test/cases | |
parent | 20b94af9eb9305d19a343f72f0afb18eb49e2de7 (diff) | |
download | rails-63ff495bdf90e0ab20114a49db5cffe3cb9ef2fd.tar.gz rails-63ff495bdf90e0ab20114a49db5cffe3cb9ef2fd.tar.bz2 rails-63ff495bdf90e0ab20114a49db5cffe3cb9ef2fd.zip |
Fix dirty tracking after rollback.
Currently the rollback only restores primary key value, `new_record?`,
`destroyed?`, and `frozen?`. Since the `save` clears current dirty
attribute states, retrying save after rollback will causes no change
saved if partial writes is enabled (by default).
This makes `remember_transaction_record_state` remembers original values
then restores dirty attribute states after rollback.
Fixes #15018.
Fixes #30167.
Fixes #33868.
Fixes #33443.
Closes #33444.
Closes #34504.
Diffstat (limited to 'activerecord/test/cases')
-rw-r--r-- | activerecord/test/cases/transactions_test.rb | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb index 7bad3de343..6795996cca 100644 --- a/activerecord/test/cases/transactions_test.rb +++ b/activerecord/test/cases/transactions_test.rb @@ -18,6 +18,65 @@ class TransactionTest < ActiveRecord::TestCase @first, @second = Topic.find(1, 2).sort_by(&:id) end + def test_rollback_dirty_changes + topic = topics(:fifth) + + ActiveRecord::Base.transaction do + topic.update(title: "Ruby on Rails") + raise ActiveRecord::Rollback + end + + title_change = ["The Fifth Topic of the day", "Ruby on Rails"] + assert_equal title_change, topic.changes["title"] + end + + def test_rollback_dirty_changes_multiple_saves + topic = topics(:fifth) + + ActiveRecord::Base.transaction do + topic.update(title: "Ruby on Rails") + topic.update(title: "Another Title") + raise ActiveRecord::Rollback + end + + title_change = ["The Fifth Topic of the day", "Another Title"] + assert_equal title_change, topic.changes["title"] + end + + def test_rollback_dirty_changes_then_retry_save + topic = topics(:fifth) + + ActiveRecord::Base.transaction do + topic.update(title: "Ruby on Rails") + raise ActiveRecord::Rollback + end + + title_change = ["The Fifth Topic of the day", "Ruby on Rails"] + assert_equal title_change, topic.changes["title"] + + assert topic.save + + assert_equal title_change, topic.saved_changes["title"] + assert_equal topic.title, topic.reload.title + end + + def test_rollback_dirty_changes_then_retry_save_on_new_record + topic = Topic.new(title: "Ruby on Rails") + + ActiveRecord::Base.transaction do + topic.save + raise ActiveRecord::Rollback + end + + title_change = [nil, "Ruby on Rails"] + assert_equal title_change, topic.changes["title"] + + assert topic.save + + assert_equal title_change, topic.saved_changes["title"] + assert_equal topic.title, topic.reload.title + end + def test_persisted_in_a_model_with_custom_primary_key_after_failed_save movie = Movie.create assert_not_predicate movie, :persisted? |