1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Extract attribute serialization code into a separate module

This commit is contained in:
Jon Leighton 2011-11-30 15:52:09 +00:00
parent 61489dc684
commit f4853dc174
4 changed files with 49 additions and 28 deletions

View file

@ -92,6 +92,7 @@ module ActiveRecord
autoload :Read
autoload :TimeZoneConversion
autoload :Write
autoload :Serialization
end
end

View file

@ -34,22 +34,12 @@ module ActiveRecord
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 @@ module ActiveRecord
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

View file

@ -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

View file

@ -2219,6 +2219,7 @@ MSG
include AttributeMethods::PrimaryKey
include AttributeMethods::TimeZoneConversion
include AttributeMethods::Dirty
include AttributeMethods::Serialization
include ActiveModel::MassAssignmentSecurity
include Callbacks, ActiveModel::Observing, Timestamp
include Associations, NamedScope