diff options
Diffstat (limited to 'activerecord/lib/active_record/attribute_methods/serialization.rb')
-rw-r--r-- | activerecord/lib/active_record/attribute_methods/serialization.rb | 52 |
1 files changed, 34 insertions, 18 deletions
diff --git a/activerecord/lib/active_record/attribute_methods/serialization.rb b/activerecord/lib/active_record/attribute_methods/serialization.rb index ac65ef94f9..bc7e9d7a94 100644 --- a/activerecord/lib/active_record/attribute_methods/serialization.rb +++ b/activerecord/lib/active_record/attribute_methods/serialization.rb @@ -10,6 +10,26 @@ module ActiveRecord self.serialized_attributes = {} end + class Attribute < Struct.new(:coder, :value, :state) + def unserialized_value + state == :serialized ? unserialize : value + end + + def serialized_value + state == :unserialized ? serialize : value + end + + def unserialize + self.state = :unserialized + self.value = coder.load(value) + end + + def serialize + self.state = :serialized + self.value = coder.dump(value) + end + end + module ClassMethods # If you have an attribute that needs to be saved to the database as an object, and retrieved as the same object, # then specify the name of that attribute using this method and it will be handled automatically. @@ -42,7 +62,7 @@ module ActiveRecord if serialized_attributes.include?(attr_name) generated_attribute_methods.module_eval(<<-CODE, __FILE__, __LINE__) def _#{attr_name} - @attributes_cache['#{attr_name}'] ||= @attributes['#{attr_name}'] + @attributes['#{attr_name}'].unserialized_value end alias #{attr_name} _#{attr_name} CODE @@ -50,31 +70,27 @@ module ActiveRecord super end end - - def cacheable_column?(column) - serialized_attributes.include?(column.name) || super - end end def set_serialized_attributes - sattrs = self.class.serialized_attributes - - sattrs.each do |key, coder| - @attributes[key] = coder.load @attributes[key] if @attributes.key?(key) + self.class.serialized_attributes.each do |key, coder| + if @attributes.key?(key) + @attributes[key] = Attribute.new(coder, @attributes[key], :serialized) + end end end def type_cast_attribute(column) - coder = self.class.serialized_attributes[column.name] - - if column.text? && coder - unserialized_object = coder.load(@attributes[column.name]) + if column.text? && self.class.serialized_attributes.include?(column.name) + @attributes[column.name].unserialized_value + else + super + end + end - if @attributes.frozen? - unserialized_object - else - @attributes[column.name] = unserialized_object - end + def type_cast_attribute_for_write(column, attr_name, value) + if column && coder = self.class.serialized_attributes[column.name] + Attribute.new(coder, value, :unserialized) else super end |