提交 f4853dc1 编写于 作者: J Jon Leighton

Extract attribute serialization code into a separate module

上级 61489dc6
......@@ -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
......
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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册