Permalink
Browse files

Extract attribute serialization code into a separate module

  • Loading branch information...
1 parent 61489dc commit f4853dc17490c88966721ca1ad422baf6ae49745 @jonleighton jonleighton committed Nov 30, 2011
@@ -92,6 +92,7 @@ module AttributeMethods
autoload :Read
autoload :TimeZoneConversion
autoload :Write
+ autoload :Serialization
end
end
@@ -34,22 +34,12 @@ def cache_attribute?(attr_name)
protected
def define_method_attribute(attr_name)
- if serialized_attributes.include?(attr_name)
- define_read_method_for_serialized_attribute(attr_name)
- else
- define_read_method(attr_name, attr_name, columns_hash[attr_name])
- end
+ define_read_method(attr_name, attr_name, columns_hash[attr_name])
end
private
def cacheable_column?(column)
- serialized_attributes.include?(column.name) || attribute_types_cached_by_default.include?(column.type)
- end
-
- # Define read method for serialized attribute.
- def define_read_method_for_serialized_attribute(attr_name)
- access_code = "@attributes_cache['#{attr_name}'] ||= @attributes['#{attr_name}']"
- generated_attribute_methods.module_eval("def _#{attr_name}; #{access_code}; end; alias #{attr_name} _#{attr_name}", __FILE__, __LINE__)
+ attribute_types_cached_by_default.include?(column.type)
end
# Define an attribute reader method. Cope with nil column.
@@ -107,28 +97,15 @@ def _read_attribute(attr_name)
value = @attributes[attr_name]
unless value.nil?
if column = column_for_attribute(attr_name)
- if unserializable_attribute?(attr_name, column)
- unserialize_attribute(attr_name)
- else
- column.type_cast(value)
- end
+ type_cast_attribute(column, value)
else
value
end
end
end
- # Returns true if the attribute is of a text column and marked for serialization.
- def unserializable_attribute?(attr_name, column)
- column.text? && self.class.serialized_attributes.include?(attr_name)
- end
-
- # Returns the unserialized object of the attribute.
- def unserialize_attribute(attr_name)
- coder = self.class.serialized_attributes[attr_name]
- unserialized_object = coder.load(@attributes[attr_name])
-
- @attributes.frozen? ? unserialized_object : @attributes[attr_name] = unserialized_object
+ def type_cast_attribute(column, value) #:nodoc:
+ column.type_cast(value)
end
private
@@ -0,0 +1,42 @@
+module ActiveRecord
+ module AttributeMethods
+ module Serialization
+ extend ActiveSupport::Concern
+
+ module ClassMethods
+ def define_method_attribute(attr_name)
+ if serialized_attributes.include?(attr_name)
+ generated_attribute_methods.module_eval(<<-CODE, __FILE__, __LINE__)
+ def _#{attr_name}
+ @attributes_cache['#{attr_name}'] ||= @attributes['#{attr_name}']
+ end
+ alias #{attr_name} _#{attr_name}
+ CODE
+ else
+ super
+ end
+ end
+
+ def cacheable_column?(column)
+ serialized_attributes.include?(column.name) || super
+ end
+ end
+
+ def type_cast_attribute(column, value)
+ coder = self.class.serialized_attributes[column.name]
+
+ if column.text? && coder
+ unserialized_object = coder.load(@attributes[column.name])
+
+ if @attributes.frozen?
+ unserialized_object
+ else
+ @attributes[column.name] = unserialized_object
+ end
+ else
+ super
+ end
+ end
+ end
+ end
+end
@@ -2219,6 +2219,7 @@ def populate_with_current_scope_attributes
include AttributeMethods::PrimaryKey
include AttributeMethods::TimeZoneConversion
include AttributeMethods::Dirty
+ include AttributeMethods::Serialization
include ActiveModel::MassAssignmentSecurity
include Callbacks, ActiveModel::Observing, Timestamp
include Associations, NamedScope

0 comments on commit f4853dc

Please sign in to comment.