diff options
author | Eugene Kenny <elkenny@gmail.com> | 2017-03-13 02:01:18 +0000 |
---|---|---|
committer | Eugene Kenny <elkenny@gmail.com> | 2017-07-09 01:26:20 +0100 |
commit | b19c4eff47d912ee3a038a6e0653eea7df5b67b8 (patch) | |
tree | 7412e9d3c3e019d6f6e93ff1e328836412ecca65 /activerecord/test/cases | |
parent | 72e1c4229ab0af6a76c1635adff76fc02fa7fe71 (diff) | |
download | rails-b19c4eff47d912ee3a038a6e0653eea7df5b67b8.tar.gz rails-b19c4eff47d912ee3a038a6e0653eea7df5b67b8.tar.bz2 rails-b19c4eff47d912ee3a038a6e0653eea7df5b67b8.zip |
Sync transaction state when accessing primary key
If a record is modified inside a transaction, it must check the outcome
of that transaction before accessing any state which would no longer be
valid if it was rolled back.
For example, consider a new record that was saved inside a transaction
which was later rolled back: it should be restored to its previous state
so that saving it again inserts a new row into the database instead of
trying to update a row that no longer exists.
The `id` and `id=` methods defined on the PrimaryKey module implement
this correctly, but when a model uses a custom primary key, the reader
and writer methods for that attribute must check the transaction state
too. The `read_attribute` and `write_attribute` methods also need to
check the transaction state when accessing the primary key.
Diffstat (limited to 'activerecord/test/cases')
-rw-r--r-- | activerecord/test/cases/transactions_test.rb | 52 |
1 files changed, 49 insertions, 3 deletions
diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb index 76a997ba8b..a5348e2825 100644 --- a/activerecord/test/cases/transactions_test.rb +++ b/activerecord/test/cases/transactions_test.rb @@ -684,7 +684,7 @@ class TransactionTest < ActiveRecord::TestCase raise ActiveRecord::Rollback end - assert_nil movie.id + assert_nil movie.movieid end def test_assign_id_after_rollback @@ -707,8 +707,54 @@ class TransactionTest < ActiveRecord::TestCase raise ActiveRecord::Rollback end - movie.id = nil - assert_nil movie.id + movie.movieid = nil + assert_nil movie.movieid + end + + def test_read_attribute_after_rollback + topic = Topic.new + + Topic.transaction do + topic.save! + raise ActiveRecord::Rollback + end + + assert_nil topic.read_attribute(:id) + end + + def test_read_attribute_with_custom_primary_key_after_rollback + movie = Movie.new(name: "foo") + + Movie.transaction do + movie.save! + raise ActiveRecord::Rollback + end + + assert_nil movie.read_attribute(:movieid) + end + + def test_write_attribute_after_rollback + topic = Topic.create! + + Topic.transaction do + topic.save! + raise ActiveRecord::Rollback + end + + topic.write_attribute(:id, nil) + assert_nil topic.id + end + + def test_write_attribute_with_custom_primary_key_after_rollback + movie = Movie.create!(name: "foo") + + Movie.transaction do + movie.save! + raise ActiveRecord::Rollback + end + + movie.write_attribute(:movieid, nil) + assert_nil movie.movieid end def test_rollback_of_frozen_records |