aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/attribute_methods
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record/attribute_methods')
-rw-r--r--activerecord/lib/active_record/attribute_methods/serialization.rb65
-rw-r--r--activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb6
-rw-r--r--activerecord/lib/active_record/attribute_methods/write.rb19
3 files changed, 15 insertions, 75 deletions
diff --git a/activerecord/lib/active_record/attribute_methods/serialization.rb b/activerecord/lib/active_record/attribute_methods/serialization.rb
index 53a9c874bf..65d910fd46 100644
--- a/activerecord/lib/active_record/attribute_methods/serialization.rb
+++ b/activerecord/lib/active_record/attribute_methods/serialization.rb
@@ -58,53 +58,18 @@ module ActiveRecord
Coders::YAMLColumn.new(class_name_or_coder)
end
+ type = columns_hash[attr_name.to_s].cast_type
+ if type.serialized?
+ type = type.subtype
+ end
+ property attr_name, Type::Serialized.new(type, coder)
+
# merge new serialized attribute and create new hash to ensure that each class in inheritance hierarchy
# has its own hash of own serialized attributes
self.serialized_attributes = serialized_attributes.merge(attr_name.to_s => coder)
end
end
- class Type # :nodoc:
- def initialize(column)
- @column = column
- end
-
- def type_cast(value)
- if value.state == :serialized
- value.unserialized_value @column.type_cast value.value
- else
- value.unserialized_value
- end
- end
-
- def type
- @column.type
- end
-
- def accessor
- ActiveRecord::Store::IndifferentHashAccessor
- end
- end
-
- class Attribute < Struct.new(:coder, :value, :state) # :nodoc:
- def unserialized_value(v = value)
- state == :serialized ? unserialize(v) : value
- end
-
- def serialized_value
- state == :unserialized ? serialize : value
- end
-
- def unserialize(v)
- self.state = :unserialized
- self.value = coder.load(v)
- end
-
- def serialize
- self.state = :serialized
- self.value = coder.dump(value)
- end
- end
# This is only added to the model when serialize is called, which
# ensures we do not make things slower when serialization is not used.
@@ -118,7 +83,7 @@ module ActiveRecord
serialized_attributes.each do |key, coder|
if attributes.key?(key)
- attributes[key] = Attribute.new(coder, attributes[key], serialized)
+ attributes[key] = Type::Serialized::Attribute.new(coder, attributes[key], serialized)
end
end
@@ -134,22 +99,6 @@ module ActiveRecord
super | (attributes.keys & self.class.serialized_attributes.keys)
end
- def type_cast_attribute_for_write(column, value)
- if column && coder = self.class.serialized_attributes[column.name]
- Attribute.new(coder, value, :unserialized)
- else
- super
- 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
diff --git a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
index dfebb2cf56..6149ac4906 100644
--- a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
+++ b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
@@ -2,6 +2,8 @@ module ActiveRecord
module AttributeMethods
module TimeZoneConversion
class Type # :nodoc:
+ delegate :type, :type_cast_for_database, to: :@column
+
def initialize(column)
@column = column
end
@@ -10,10 +12,6 @@ module ActiveRecord
value = @column.type_cast(value)
value.acts_like?(:time) ? value.in_time_zone : value
end
-
- def type
- @column.type
- end
end
extend ActiveSupport::Concern
diff --git a/activerecord/lib/active_record/attribute_methods/write.rb b/activerecord/lib/active_record/attribute_methods/write.rb
index 56441d7324..629bd3bc63 100644
--- a/activerecord/lib/active_record/attribute_methods/write.rb
+++ b/activerecord/lib/active_record/attribute_methods/write.rb
@@ -26,8 +26,6 @@ module ActiveRecord
protected
if Module.methods_transplantable?
- # See define_method_attribute in read.rb for an explanation of
- # this code.
def define_method_attribute=(name)
method = WriterMethodCache[name]
generated_attribute_methods.module_eval {
@@ -55,11 +53,11 @@ module ActiveRecord
# specified +value+. Empty strings for fixnum and float columns are
# turned into +nil+.
def write_attribute(attr_name, value)
- write_attribute_with_type_cast(attr_name, value, :type_cast_attribute_for_write)
+ write_attribute_with_type_cast(attr_name, value, :type_cast_for_write)
end
def raw_write_attribute(attr_name, value)
- write_attribute_with_type_cast(attr_name, value, :raw_type_cast_attribute_for_write)
+ write_attribute_with_type_cast(attr_name, value, :raw_type_cast_for_write)
end
private
@@ -68,13 +66,6 @@ module ActiveRecord
write_attribute(attribute_name, value)
end
- def type_cast_attribute_for_write(column, value)
- return value unless column
-
- 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
@@ -87,8 +78,10 @@ module ActiveRecord
@attributes_cache[attr_name] = value
end
- if column || @attributes.has_key?(attr_name)
- @attributes[attr_name] = send(type_cast_method, column, value)
+ if column
+ @attributes[attr_name] = column.public_send(type_cast_method, value)
+ elsif @attributes.has_key?(attr_name)
+ @attributes[attr_name] = value
else
raise ActiveModel::MissingAttributeError, "can't write unknown attribute `#{attr_name}'"
end