提交 02ee081c 编写于 作者: Y Yves Senn

Merge pull request #15435 from sgrif/sg-rm-serialization

Remove most code related to serialized properties
...@@ -287,11 +287,6 @@ def attributes ...@@ -287,11 +287,6 @@ def attributes
} }
end end
# Placeholder so it can be overriden when needed by serialization
def attributes_for_coder # :nodoc:
attributes_before_type_cast
end
# Returns an <tt>#inspect</tt>-like string for the value of the # Returns an <tt>#inspect</tt>-like string for the value of the
# attribute +attr_name+. String attributes are truncated upto 50 # attribute +attr_name+. String attributes are truncated upto 50
# characters, Date and Time attributes are returned in the # characters, Date and Time attributes are returned in the
......
...@@ -94,7 +94,7 @@ def #{temp_method} ...@@ -94,7 +94,7 @@ def #{temp_method}
def cacheable_column?(column) def cacheable_column?(column)
if attribute_types_cached_by_default == ATTRIBUTE_TYPES_CACHED_BY_DEFAULT if attribute_types_cached_by_default == ATTRIBUTE_TYPES_CACHED_BY_DEFAULT
! serialized_attributes.include? column.name true
else else
attribute_types_cached_by_default.include?(column.type) attribute_types_cached_by_default.include?(column.type)
end end
......
...@@ -76,21 +76,6 @@ def serialize(attr_name, class_name_or_coder = Object) ...@@ -76,21 +76,6 @@ def serialize(attr_name, class_name_or_coder = Object)
module Behavior # :nodoc: module Behavior # :nodoc:
extend ActiveSupport::Concern extend ActiveSupport::Concern
module ClassMethods # :nodoc:
def initialize_attributes(attributes, options = {})
serialized = (options.delete(:serialized) { true }) ? :serialized : :unserialized
super(attributes, options)
serialized_attributes.each do |key, coder|
if attributes.key?(key)
attributes[key] = Type::Serialized::Attribute.new(coder, attributes[key], serialized)
end
end
attributes
end
end
def should_record_timestamps? def should_record_timestamps?
super || (self.record_timestamps && (attributes.keys & self.class.serialized_attributes.keys).present?) super || (self.record_timestamps && (attributes.keys & self.class.serialized_attributes.keys).present?)
end end
...@@ -106,42 +91,6 @@ def _field_changed?(attr, old, value) ...@@ -106,42 +91,6 @@ def _field_changed?(attr, old, value)
super super
end end
end end
def read_attribute_before_type_cast(attr_name)
if self.class.serialized_attributes.include?(attr_name)
super.unserialized_value
else
super
end
end
def attributes_before_type_cast
super.dup.tap do |attributes|
self.class.serialized_attributes.each_key do |key|
if attributes.key?(key)
attributes[key] = attributes[key].unserialized_value
end
end
end
end
def typecasted_attribute_value(name)
if self.class.serialized_attributes.include?(name)
@raw_attributes[name].serialized_value
else
super
end
end
def attributes_for_coder
attribute_names.each_with_object({}) do |name, attrs|
attrs[name] = if self.class.serialized_attributes.include?(name)
@raw_attributes[name].serialized_value
else
read_attribute_before_type_cast(name)
end
end
end
end end
end end
end end
......
...@@ -53,11 +53,11 @@ def __temp__#{safe_name}=(value) ...@@ -53,11 +53,11 @@ def __temp__#{safe_name}=(value)
# specified +value+. Empty strings for fixnum and float columns are # specified +value+. Empty strings for fixnum and float columns are
# turned into +nil+. # turned into +nil+.
def write_attribute(attr_name, value) def write_attribute(attr_name, value)
write_attribute_with_type_cast(attr_name, value, :type_cast_for_write) write_attribute_with_type_cast(attr_name, value, true)
end end
def raw_write_attribute(attr_name, value) def raw_write_attribute(attr_name, value)
write_attribute_with_type_cast(attr_name, value, :raw_type_cast_for_write) write_attribute_with_type_cast(attr_name, value, false)
end end
private private
...@@ -66,7 +66,7 @@ def attribute=(attribute_name, value) ...@@ -66,7 +66,7 @@ def attribute=(attribute_name, value)
write_attribute(attribute_name, value) write_attribute(attribute_name, value)
end end
def write_attribute_with_type_cast(attr_name, value, type_cast_method) def write_attribute_with_type_cast(attr_name, value, should_type_cast)
attr_name = attr_name.to_s attr_name = attr_name.to_s
attr_name = self.class.primary_key if attr_name == 'id' && self.class.primary_key attr_name = self.class.primary_key if attr_name == 'id' && self.class.primary_key
@attributes.delete(attr_name) @attributes.delete(attr_name)
...@@ -78,9 +78,9 @@ def write_attribute_with_type_cast(attr_name, value, type_cast_method) ...@@ -78,9 +78,9 @@ def write_attribute_with_type_cast(attr_name, value, type_cast_method)
@attributes[attr_name] = value @attributes[attr_name] = value
end end
if column if column && should_type_cast
@raw_attributes[attr_name] = column.public_send(type_cast_method, value) @raw_attributes[attr_name] = column.type_cast_for_write(value)
elsif @raw_attributes.has_key?(attr_name) elsif !should_type_cast || @raw_attributes.has_key?(attr_name)
@raw_attributes[attr_name] = value @raw_attributes[attr_name] = value
else else
raise ActiveModel::MissingAttributeError, "can't write unknown attribute `#{attr_name}'" raise ActiveModel::MissingAttributeError, "can't write unknown attribute `#{attr_name}'"
......
...@@ -17,7 +17,7 @@ module Format ...@@ -17,7 +17,7 @@ module Format
delegate :type, :precision, :scale, :limit, :klass, :accessor, delegate :type, :precision, :scale, :limit, :klass, :accessor,
:text?, :number?, :binary?, :serialized?, :text?, :number?, :binary?, :serialized?,
:type_cast, :type_cast_for_write, :raw_type_cast_for_write, :type_cast_for_database, :type_cast, :type_cast_for_write, :type_cast_for_database,
:type_cast_for_schema, :type_cast_for_schema,
to: :cast_type to: :cast_type
...@@ -52,7 +52,7 @@ def human_name ...@@ -52,7 +52,7 @@ def human_name
end end
def extract_default(default) def extract_default(default)
type_cast(default) type_cast_for_write(type_cast(default))
end end
end end
end end
......
...@@ -353,7 +353,7 @@ def initialize_dup(other) # :nodoc: ...@@ -353,7 +353,7 @@ def initialize_dup(other) # :nodoc:
# Post.new.encode_with(coder) # Post.new.encode_with(coder)
# coder # => {"attributes" => {"id" => nil, ... }} # coder # => {"attributes" => {"id" => nil, ... }}
def encode_with(coder) def encode_with(coder)
coder['attributes'] = attributes_for_coder coder['attributes'] = @raw_attributes
end end
# Returns true if +comparison_object+ is the same exact object, or +comparison_object+ # Returns true if +comparison_object+ is the same exact object, or +comparison_object+
......
...@@ -10,20 +10,21 @@ def initialize(subtype, coder) ...@@ -10,20 +10,21 @@ def initialize(subtype, coder)
end end
def type_cast(value) def type_cast(value)
if value.respond_to?(:unserialized_value) if is_default_value?(value)
value.unserialized_value(super(value.value)) value
else else
super coder.load(super)
end end
end end
def type_cast_for_write(value) def type_cast_for_write(value)
Attribute.new(coder, value, :unserialized) return if value.nil?
unless is_default_value?(value)
coder.dump(value)
end
end end
def raw_type_cast_for_write(value) alias type_cast_for_database type_cast_for_write
Attribute.new(coder, value, :serialized)
end
def serialized? def serialized?
true true
...@@ -33,24 +34,10 @@ def accessor ...@@ -33,24 +34,10 @@ def accessor
ActiveRecord::Store::IndifferentHashAccessor ActiveRecord::Store::IndifferentHashAccessor
end end
class Attribute < Struct.new(:coder, :value, :state) # :nodoc: private
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 def is_default_value?(value)
self.state = :serialized value == coder.load(nil)
self.value = coder.dump(value)
end
end end
end end
end end
......
...@@ -54,7 +54,6 @@ def klass # :nodoc: ...@@ -54,7 +54,6 @@ def klass # :nodoc:
def type_cast_for_write(value) # :nodoc: def type_cast_for_write(value) # :nodoc:
value value
end end
alias_method :raw_type_cast_for_write, :type_cast_for_write # :internal:
private private
......
...@@ -14,7 +14,6 @@ def validate_each(record, attribute, value) ...@@ -14,7 +14,6 @@ def validate_each(record, attribute, value)
finder_class = find_finder_class_for(record) finder_class = find_finder_class_for(record)
table = finder_class.arel_table table = finder_class.arel_table
value = map_enum_attribute(finder_class, attribute, value) value = map_enum_attribute(finder_class, attribute, value)
value = deserialize_attribute(record, attribute, value)
relation = build_relation(finder_class, table, attribute, value) relation = build_relation(finder_class, table, attribute, value)
relation = relation.and(table[finder_class.primary_key.to_sym].not_eq(record.id)) if record.persisted? relation = relation.and(table[finder_class.primary_key.to_sym].not_eq(record.id)) if record.persisted?
...@@ -86,12 +85,6 @@ def scope_relation(record, table, relation) ...@@ -86,12 +85,6 @@ def scope_relation(record, table, relation)
relation relation
end end
def deserialize_attribute(record, attribute, value)
coder = record.class.serialized_attributes[attribute.to_s]
value = coder.dump value if value && coder
value
end
def map_enum_attribute(klass, attribute, value) def map_enum_attribute(klass, attribute, value)
mapping = klass.defined_enums[attribute.to_s] mapping = klass.defined_enums[attribute.to_s]
value = mapping[value] if value && mapping value = mapping[value] if value && mapping
......
...@@ -93,6 +93,7 @@ def type_cast(value) ...@@ -93,6 +93,7 @@ def type_cast(value)
end end
def type_cast_for_write(value) def type_cast_for_write(value)
return if value.nil?
"(#{value.city},#{value.street})" "(#{value.city},#{value.street})"
end end
end end
......
...@@ -870,7 +870,7 @@ def new_topic_like_ar_class(&block) ...@@ -870,7 +870,7 @@ def new_topic_like_ar_class(&block)
end end
def cached_columns def cached_columns
Topic.columns.map(&:name) - Topic.serialized_attributes.keys Topic.columns.map(&:name)
end end
def time_related_columns_on_topic def time_related_columns_on_topic
......
...@@ -59,8 +59,9 @@ def test_serialized_attributes_from_database_on_subclass ...@@ -59,8 +59,9 @@ def test_serialized_attributes_from_database_on_subclass
def test_serialized_attribute_calling_dup_method def test_serialized_attribute_calling_dup_method
Topic.serialize :content, JSON Topic.serialize :content, JSON
t = Topic.new(:content => { :foo => :bar }).dup orig = Topic.new(content: { foo: :bar })
assert_equal({ :foo => :bar }, t.content_before_type_cast) clone = orig.dup
assert_equal(orig.content, clone.content)
end end
def test_serialized_attribute_declared_in_subclass def test_serialized_attribute_declared_in_subclass
...@@ -103,8 +104,10 @@ def test_nil_not_serialized_with_class_constraint ...@@ -103,8 +104,10 @@ def test_nil_not_serialized_with_class_constraint
def test_serialized_attribute_should_raise_exception_on_save_with_wrong_type def test_serialized_attribute_should_raise_exception_on_save_with_wrong_type
Topic.serialize(:content, Hash) Topic.serialize(:content, Hash)
topic = Topic.new(:content => "string") assert_raise(ActiveRecord::SerializationTypeMismatch) do
assert_raise(ActiveRecord::SerializationTypeMismatch) { topic.save } topic = Topic.new(content: 'string')
topic.save
end
end end
def test_should_raise_exception_on_serialized_attribute_with_type_mismatch def test_should_raise_exception_on_serialized_attribute_with_type_mismatch
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册