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

Don't map id to primary key in raw_write_attribute

The `raw_write_attribute` method is used to update a record's attributes
to reflect the new state of the database in `update_columns`. The hash
provided to `update_columns` is turned into an UPDATE query directly,
which means passing an `id` key results in an update to the `id` column,
even if the model uses a different attribute as its primary key. When
updating the record, we don't want to apply the `id` column change to
the primary key attribute, since that's not what happened in the query.

Without the code to handle this case, `write_attribute_with_type_cast`
no longer contains any logic shared between `raw_write_attribute` and
`write_attribute`, so we can inline the code into those two methods.
This commit is contained in:
Eugene Kenny 2017-06-15 13:00:20 +01:00
parent bbd8084ffe
commit 2e4fe3a4ad
2 changed files with 12 additions and 15 deletions

View file

@ -35,11 +35,15 @@ module ActiveRecord
attr_name.to_s
end
write_attribute_with_type_cast(name, value, true)
name = self.class.primary_key if name == "id".freeze && self.class.primary_key
@attributes.write_from_user(name, value)
value
end
def raw_write_attribute(attr_name, value) # :nodoc:
write_attribute_with_type_cast(attr_name, value, false)
name = attr_name.to_s
@attributes.write_cast_value(name, value)
value
end
private
@ -47,19 +51,6 @@ module ActiveRecord
def attribute=(attribute_name, value)
write_attribute(attribute_name, value)
end
def write_attribute_with_type_cast(attr_name, value, should_type_cast)
attr_name = attr_name.to_s
attr_name = self.class.primary_key if attr_name == "id" && self.class.primary_key
if should_type_cast
@attributes.write_from_user(attr_name, value)
else
@attributes.write_cast_value(attr_name, value)
end
value
end
end
end
end

View file

@ -80,6 +80,12 @@ class PrimaryKeysTest < ActiveRecord::TestCase
assert_equal 1, subscriber.update_count
end
def test_update_columns_with_non_primary_key_id_column
subscriber = Subscriber.first
subscriber.update_columns(id: 1)
assert_not_equal 1, subscriber.nick
end
def test_string_key
subscriber = Subscriber.find(subscribers(:first).nick)
assert_equal(subscribers(:first).name, subscriber.name)