aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Griffin <sean@thoughtbot.com>2014-05-29 13:34:23 -0700
committerSean Griffin <sean@thoughtbot.com>2014-05-29 13:34:47 -0700
commit912904caee1e037e2f71d6ede35a3758c15f276d (patch)
tree2384c2a13db76ae767f96e114870178fb93debb1
parent214423f40171bf7d3165d70507ab17803b2fbf07 (diff)
downloadrails-912904caee1e037e2f71d6ede35a3758c15f276d.tar.gz
rails-912904caee1e037e2f71d6ede35a3758c15f276d.tar.bz2
rails-912904caee1e037e2f71d6ede35a3758c15f276d.zip
Move `type_cast_for_write` behavior over to the serialized type object
-rw-r--r--activerecord/lib/active_record/attribute_methods/serialization.rb39
-rw-r--r--activerecord/lib/active_record/attribute_methods/write.rb17
-rw-r--r--activerecord/lib/active_record/connection_adapters/column.rb2
-rw-r--r--activerecord/lib/active_record/type/serialized.rb35
-rw-r--r--activerecord/lib/active_record/type/value.rb11
-rw-r--r--activerecord/test/cases/attribute_methods/serialization_test.rb29
6 files changed, 47 insertions, 86 deletions
diff --git a/activerecord/lib/active_record/attribute_methods/serialization.rb b/activerecord/lib/active_record/attribute_methods/serialization.rb
index e8c27cb8b8..65d910fd46 100644
--- a/activerecord/lib/active_record/attribute_methods/serialization.rb
+++ b/activerecord/lib/active_record/attribute_methods/serialization.rb
@@ -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
diff --git a/activerecord/lib/active_record/attribute_methods/write.rb b/activerecord/lib/active_record/attribute_methods/write.rb
index 56441d7324..d552bea8c4 100644
--- a/activerecord/lib/active_record/attribute_methods/write.rb
+++ b/activerecord/lib/active_record/attribute_methods/write.rb
@@ -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
diff --git a/activerecord/lib/active_record/connection_adapters/column.rb b/activerecord/lib/active_record/connection_adapters/column.rb
index 42650e332d..f66e99c9d1 100644
--- a/activerecord/lib/active_record/connection_adapters/column.rb
+++ b/activerecord/lib/active_record/connection_adapters/column.rb
@@ -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.
diff --git a/activerecord/lib/active_record/type/serialized.rb b/activerecord/lib/active_record/type/serialized.rb
index cc7513ca2a..4052ac0fa0 100644
--- a/activerecord/lib/active_record/type/serialized.rb
+++ b/activerecord/lib/active_record/type/serialized.rb
@@ -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
diff --git a/activerecord/lib/active_record/type/value.rb b/activerecord/lib/active_record/type/value.rb
index a5493be8f2..9a4adc60cc 100644
--- a/activerecord/lib/active_record/type/value.rb
+++ b/activerecord/lib/active_record/type/value.rb
@@ -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
diff --git a/activerecord/test/cases/attribute_methods/serialization_test.rb b/activerecord/test/cases/attribute_methods/serialization_test.rb
deleted file mode 100644
index 2e3bcadab1..0000000000
--- a/activerecord/test/cases/attribute_methods/serialization_test.rb
+++ /dev/null
@@ -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