mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #14613 from Sirupsen/fix-serialize-update-column
Fix serialized field returning serialized data after update_column Conflicts: activerecord/CHANGELOG.md
This commit is contained in:
commit
94e7dbce8a
4 changed files with 54 additions and 17 deletions
|
@ -1,3 +1,8 @@
|
|||
* Fixed serialized fields returning serialized data after being updated with
|
||||
`update_column`.
|
||||
|
||||
*Simon Hørup Eskildsen*
|
||||
|
||||
* Fixed polymorphic eager loading when using a String as foreign key.
|
||||
|
||||
Fixes #14734.
|
||||
|
|
|
@ -142,6 +142,14 @@ module ActiveRecord
|
|||
end
|
||||
end
|
||||
|
||||
def raw_type_cast_attribute_for_write(column, value)
|
||||
if column && coder = self.class.serialized_attributes[column.name]
|
||||
Attribute.new(coder, value, :serialized)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
def _field_changed?(attr, old, value)
|
||||
if self.class.serialized_attributes.include?(attr)
|
||||
old != value
|
||||
|
|
|
@ -55,24 +55,12 @@ module ActiveRecord
|
|||
# specified +value+. Empty strings for fixnum and float columns are
|
||||
# turned into +nil+.
|
||||
def write_attribute(attr_name, value)
|
||||
attr_name = attr_name.to_s
|
||||
attr_name = self.class.primary_key if attr_name == 'id' && self.class.primary_key
|
||||
@attributes_cache.delete(attr_name)
|
||||
column = column_for_attribute(attr_name)
|
||||
|
||||
# If we're dealing with a binary column, write the data to the cache
|
||||
# so we don't attempt to typecast multiple times.
|
||||
if column && column.binary?
|
||||
@attributes_cache[attr_name] = value
|
||||
write_attribute_with_type_cast(attr_name, value, :type_cast_attribute_for_write)
|
||||
end
|
||||
|
||||
if column || @attributes.has_key?(attr_name)
|
||||
@attributes[attr_name] = type_cast_attribute_for_write(column, value)
|
||||
else
|
||||
raise ActiveModel::MissingAttributeError, "can't write unknown attribute `#{attr_name}'"
|
||||
def raw_write_attribute(attr_name, value)
|
||||
write_attribute_with_type_cast(attr_name, value, :raw_type_cast_attribute_for_write)
|
||||
end
|
||||
end
|
||||
alias_method :raw_write_attribute, :write_attribute
|
||||
|
||||
private
|
||||
# Handle *= for method_missing.
|
||||
|
@ -85,6 +73,26 @@ module ActiveRecord
|
|||
|
||||
column.type_cast_for_write value
|
||||
end
|
||||
alias_method :raw_type_cast_attribute_for_write, :type_cast_attribute_for_write
|
||||
|
||||
def write_attribute_with_type_cast(attr_name, value, type_cast_method)
|
||||
attr_name = attr_name.to_s
|
||||
attr_name = self.class.primary_key if attr_name == 'id' && self.class.primary_key
|
||||
@attributes_cache.delete(attr_name)
|
||||
column = column_for_attribute(attr_name)
|
||||
|
||||
# If we're dealing with a binary column, write the data to the cache
|
||||
# so we don't attempt to typecast multiple times.
|
||||
if column && column.binary?
|
||||
@attributes_cache[attr_name] = value
|
||||
end
|
||||
|
||||
if column || @attributes.has_key?(attr_name)
|
||||
@attributes[attr_name] = send(type_cast_method, column, value)
|
||||
else
|
||||
raise ActiveModel::MissingAttributeError, "can't write unknown attribute `#{attr_name}'"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -244,4 +244,20 @@ class SerializedAttributeTest < ActiveRecord::TestCase
|
|||
type = Topic.column_types["content"]
|
||||
assert !type.instance_variable_get("@column").is_a?(ActiveRecord::AttributeMethods::Serialization::Type)
|
||||
end
|
||||
|
||||
def test_serialized_column_should_unserialize_after_update_column
|
||||
t = Topic.create(content: "first")
|
||||
assert_equal("first", t.content)
|
||||
|
||||
t.update_column(:content, Topic.serialized_attributes["content"].dump("second"))
|
||||
assert_equal("second", t.content)
|
||||
end
|
||||
|
||||
def test_serialized_column_should_unserialize_after_update_attribute
|
||||
t = Topic.create(content: "first")
|
||||
assert_equal("first", t.content)
|
||||
|
||||
t.update_attribute(:content, "second")
|
||||
assert_equal("second", t.content)
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue