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

Move type_cast_for_write behavior over to the serialized type object

This commit is contained in:
Sean Griffin 2014-05-29 13:34:23 -07:00
parent 214423f401
commit 912904caee
6 changed files with 47 additions and 86 deletions

View file

@ -62,7 +62,7 @@ module ActiveRecord
if type.serialized?
type = type.subtype
end
property attr_name, ActiveRecord::Type::Serialized.new(type)
property attr_name, Type::Serialized.new(type, coder)
# merge new serialized attribute and create new hash to ensure that each class in inheritance hierarchy
# has its own hash of own serialized attributes
@ -70,25 +70,6 @@ module ActiveRecord
end
end
class Attribute < Struct.new(:coder, :value, :state) # :nodoc:
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
self.state = :serialized
self.value = coder.dump(value)
end
end
# This is only added to the model when serialize is called, which
# ensures we do not make things slower when serialization is not used.
@ -102,7 +83,7 @@ module ActiveRecord
serialized_attributes.each do |key, coder|
if attributes.key?(key)
attributes[key] = Attribute.new(coder, attributes[key], serialized)
attributes[key] = Type::Serialized::Attribute.new(coder, attributes[key], serialized)
end
end
@ -118,22 +99,6 @@ module ActiveRecord
super | (attributes.keys & self.class.serialized_attributes.keys)
end
def type_cast_attribute_for_write(column, value)
if column && coder = self.class.serialized_attributes[column.name]
Attribute.new(coder, value, :unserialized)
else
super
end
end
def raw_type_cast_attribute_for_write(column, value)
if column && coder = self.class.serialized_attributes[column.name]
Attribute.new(coder, value, :serialized)
else
super
end
end
def _field_changed?(attr, old, value)
if self.class.serialized_attributes.include?(attr)
old != value

View file

@ -55,11 +55,11 @@ module ActiveRecord
# specified +value+. Empty strings for fixnum and float columns are
# turned into +nil+.
def write_attribute(attr_name, value)
write_attribute_with_type_cast(attr_name, value, :type_cast_attribute_for_write)
write_attribute_with_type_cast(attr_name, value, :type_cast_for_write)
end
def raw_write_attribute(attr_name, value)
write_attribute_with_type_cast(attr_name, value, :raw_type_cast_attribute_for_write)
write_attribute_with_type_cast(attr_name, value, :raw_type_cast_for_write)
end
private
@ -68,13 +68,6 @@ module ActiveRecord
write_attribute(attribute_name, value)
end
def type_cast_attribute_for_write(column, value)
return value unless column
column.type_cast_for_write value
end
alias_method :raw_type_cast_attribute_for_write, :type_cast_attribute_for_write
def write_attribute_with_type_cast(attr_name, value, type_cast_method)
attr_name = attr_name.to_s
attr_name = self.class.primary_key if attr_name == 'id' && self.class.primary_key
@ -87,8 +80,10 @@ module ActiveRecord
@attributes_cache[attr_name] = value
end
if column || @attributes.has_key?(attr_name)
@attributes[attr_name] = send(type_cast_method, column, value)
if column
@attributes[attr_name] = column.public_send(type_cast_method, value)
elsif @attributes.has_key?(attr_name)
@attributes[attr_name] = value
else
raise ActiveModel::MissingAttributeError, "can't write unknown attribute `#{attr_name}'"
end

View file

@ -17,7 +17,7 @@ module ActiveRecord
delegate :type, :precision, :scale, :limit, :klass, :accessor,
:text?, :number?, :binary?, :serialized?,
:type_cast, :type_cast_for_write, :type_cast_for_database,
:type_cast, :type_cast_for_write, :raw_type_cast_for_write, :type_cast_for_database,
to: :cast_type
# Instantiates a new column in the table.

View file

@ -1,11 +1,12 @@
module ActiveRecord
module Type
class Serialized < SimpleDelegator # :nodoc:
attr_reader :subtype
attr_reader :subtype, :coder
def initialize(subtype)
def initialize(subtype, coder)
@subtype = subtype
super
@coder = coder
super(subtype)
end
def type_cast(value)
@ -16,6 +17,14 @@ module ActiveRecord
end
end
def type_cast_for_write(value)
Attribute.new(coder, value, :unserialized)
end
def raw_type_cast_for_write(value)
Attribute.new(coder, value, :serialized)
end
def serialized?
true
end
@ -23,6 +32,26 @@ module ActiveRecord
def accessor
ActiveRecord::Store::IndifferentHashAccessor
end
class Attribute < Struct.new(:coder, :value, :state) # :nodoc:
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
self.state = :serialized
self.value = coder.dump(value)
end
end
end
end
end

View file

@ -23,10 +23,6 @@ module ActiveRecord
cast_value(value) unless value.nil?
end
def type_cast_for_write(value)
value
end
def type_cast_for_database(value)
type_cast_for_write(value)
end
@ -47,10 +43,15 @@ module ActiveRecord
false
end
def klass
def klass # :nodoc:
::Object
end
def type_cast_for_write(value) # :nodoc:
value
end
alias_method :raw_type_cast_for_write, :type_cast_for_write # :internal:
private
# Responsible for casting values from external sources to the appropriate

View file

@ -1,29 +0,0 @@
require "cases/helper"
module ActiveRecord
module AttributeMethods
class SerializationTest < ActiveSupport::TestCase
class FakeColumn < Struct.new(:name)
def type; :integer; end
def type_cast(s); "#{s}!"; end
end
class NullCoder
def load(v); v; end
end
def test_type_cast_serialized_value
value = Serialization::Attribute.new(NullCoder.new, "Hello world", :serialized)
type = Type::Serialized.new(FakeColumn.new)
assert_equal "Hello world!", type.type_cast(value)
end
def test_type_cast_unserialized_value
value = Serialization::Attribute.new(nil, "Hello world", :unserialized)
type = Type::Serialized.new(FakeColumn.new)
type.type_cast(value)
assert_equal "Hello world", type.type_cast(value)
end
end
end
end