1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Merge pull request #29724 from eugeneius/sync_primary_key

Sync transaction state when accessing primary key
This commit is contained in:
Matthew Draper 2017-08-02 17:21:07 +09:30 committed by GitHub
commit ac6cd6800a
4 changed files with 57 additions and 5 deletions

View file

@ -31,9 +31,11 @@ module ActiveRecord
temp_method = "__temp__#{safe_name}"
ActiveRecord::AttributeMethods::AttrNames.set_name_cache safe_name, name
sync_with_transaction_state = "sync_with_transaction_state" if name == primary_key
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
def #{temp_method}
#{sync_with_transaction_state}
name = ::ActiveRecord::AttributeMethods::AttrNames::ATTR_#{safe_name}
_read_attribute(name) { |n| missing_attribute(n, caller) }
end
@ -57,6 +59,7 @@ module ActiveRecord
end
name = self.class.primary_key if name == "id".freeze && self.class.primary_key
sync_with_transaction_state if name == self.class.primary_key
_read_attribute(name, &block)
end

View file

@ -15,10 +15,12 @@ module ActiveRecord
def define_method_attribute=(name)
safe_name = name.unpack("h*".freeze).first
ActiveRecord::AttributeMethods::AttrNames.set_name_cache safe_name, name
sync_with_transaction_state = "sync_with_transaction_state" if name == primary_key
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
def __temp__#{safe_name}=(value)
name = ::ActiveRecord::AttributeMethods::AttrNames::ATTR_#{safe_name}
#{sync_with_transaction_state}
_write_attribute(name, value)
end
alias_method #{(name + '=').inspect}, :__temp__#{safe_name}=
@ -38,6 +40,7 @@ module ActiveRecord
end
name = self.class.primary_key if name == "id".freeze && self.class.primary_key
sync_with_transaction_state if name == self.class.primary_key
_write_attribute(name, value)
end

View file

@ -432,8 +432,8 @@ module ActiveRecord
@new_record = restore_state[:new_record]
@destroyed = restore_state[:destroyed]
pk = self.class.primary_key
if pk && read_attribute(pk) != restore_state[:id]
write_attribute(pk, restore_state[:id])
if pk && _read_attribute(pk) != restore_state[:id]
_write_attribute(pk, restore_state[:id])
end
freeze if restore_state[:frozen?]
end

View file

@ -686,7 +686,7 @@ class TransactionTest < ActiveRecord::TestCase
raise ActiveRecord::Rollback
end
assert_nil movie.id
assert_nil movie.movieid
end
def test_assign_id_after_rollback
@ -709,8 +709,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