diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb index 1cf3aba41c88..c152a246b557 100644 --- a/activerecord/lib/active_record/attribute_methods/read.rb +++ b/activerecord/lib/active_record/attribute_methods/read.rb @@ -109,13 +109,14 @@ def read_attribute(attr_name) # We use #[] first as a perf optimization for non-nil values. See https://gist.github.com/jonleighton/3552829. name = attr_name.to_s @attributes_cache[name] || @attributes_cache.fetch(name) { - column = @columns_hash.fetch(name) { - return @attributes.fetch(name) { - if name == 'id' && self.class.primary_key != name - read_attribute(self.class.primary_key) - end - } - } + column = @column_types_override[name] if @column_types_override + column ||= @column_types[name] + + return @attributes.fetch(name) { + if name == 'id' && self.class.primary_key != name + read_attribute(self.class.primary_key) + end + } unless column value = @attributes.fetch(name) { return block_given? ? yield(name) : nil diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index 2b1e997ef4c7..b4d6474caa4a 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -168,7 +168,8 @@ def initialize(attributes = nil) defaults.each { |k, v| defaults[k] = v.dup if v.duplicable? } @attributes = self.class.initialize_attributes(defaults) - @columns_hash = self.class.column_types.dup + @column_types_override = nil + @column_types = self.class.column_types init_internals init_changed_attributes @@ -193,7 +194,8 @@ def initialize(attributes = nil) # post.title # => 'hello world' def init_with(coder) @attributes = self.class.initialize_attributes(coder['attributes']) - @columns_hash = self.class.column_types.merge(coder['column_types'] || {}) + @column_types_override = coder['column_types'] + @column_types = self.class.column_types init_internals diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb index 582006ea7d99..2f3fc7bd50be 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -383,9 +383,10 @@ def reload(options = nil) end @attributes.update(fresh_object.instance_variable_get('@attributes')) - @columns_hash = fresh_object.instance_variable_get('@columns_hash') - @attributes_cache = {} + @column_types = self.class.column_types + @column_types_override = fresh_object.instance_variable_get('@columns_types_override') + @attributes_cache = {} self end diff --git a/activerecord/test/cases/serialized_attribute_test.rb b/activerecord/test/cases/serialized_attribute_test.rb index b49c27bc78f1..24c5f330a104 100644 --- a/activerecord/test/cases/serialized_attribute_test.rb +++ b/activerecord/test/cases/serialized_attribute_test.rb @@ -245,7 +245,7 @@ def test_serialized_column_should_not_be_wrapped_twice Topic.create(content: myobj) Topic.all.each do |topic| - type = topic.instance_variable_get("@columns_hash")["content"] + type = Topic.column_types["content"] assert !type.instance_variable_get("@column").is_a?(ActiveRecord::AttributeMethods::Serialization::Type) end end