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:
parent
214423f401
commit
912904caee
6 changed files with 47 additions and 86 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
Loading…
Reference in a new issue