提交 99820fbe 编写于 作者: K Kir Shatrov

Report the attribute on ActiveRecord::SerializationTypeMismatch

上级 20107ff6
......@@ -54,7 +54,7 @@ def serialize(attr_name, class_name_or_coder = Object)
elsif [:load, :dump].all? { |x| class_name_or_coder.respond_to?(x) }
class_name_or_coder
else
Coders::YAMLColumn.new(class_name_or_coder)
Coders::YAMLColumn.new(attr_name, class_name_or_coder)
end
decorate_attribute_type(attr_name, :serialize) do |type|
......
......@@ -5,7 +5,8 @@ module Coders # :nodoc:
class YAMLColumn # :nodoc:
attr_accessor :object_class
def initialize(object_class = Object)
def initialize(attr_name, object_class = Object)
@attr_name = attr_name
@object_class = object_class
check_arity_of_constructor
end
......@@ -31,7 +32,7 @@ def load(yaml)
def assert_valid_value(obj)
unless obj.nil? || obj.is_a?(object_class)
raise SerializationTypeMismatch,
"Attribute was supposed to be a #{object_class}, but was a #{obj.class}. -- #{obj.inspect}"
"Attribute `#{@attr_name}` was supposed to be a #{object_class}, but was a #{obj.class}. -- #{obj.inspect}"
end
end
......
......@@ -78,7 +78,7 @@ class << self
module ClassMethods
def store(store_attribute, options = {})
serialize store_attribute, IndifferentCoder.new(options[:coder])
serialize store_attribute, IndifferentCoder.new(store_attribute, options[:coder])
store_accessor(store_attribute, options[:accessors]) if options.has_key? :accessors
end
......@@ -177,12 +177,12 @@ def self.prepare(object, store_attribute)
end
class IndifferentCoder # :nodoc:
def initialize(coder_or_class_name)
def initialize(attr_name, coder_or_class_name)
@coder =
if coder_or_class_name.respond_to?(:load) && coder_or_class_name.respond_to?(:dump)
coder_or_class_name
else
ActiveRecord::Coders::YAMLColumn.new(coder_or_class_name || Object)
ActiveRecord::Coders::YAMLColumn.new(attr_name, coder_or_class_name || Object)
end
end
......
......@@ -5,46 +5,48 @@ module ActiveRecord
module Coders
class YAMLColumnTest < ActiveRecord::TestCase
def test_initialize_takes_class
coder = YAMLColumn.new(Object)
coder = YAMLColumn.new("attr_name", Object)
assert_equal Object, coder.object_class
end
def test_type_mismatch_on_different_classes_on_dump
coder = YAMLColumn.new(Array)
assert_raises(SerializationTypeMismatch) do
coder = YAMLColumn.new("attr_name", Array)
error = assert_raises(SerializationTypeMismatch) do
coder.dump("a")
end
assert_equal %{Attribute `attr_name` was supposed to be a Array, but was a String. -- "a"}, error.to_s
end
def test_type_mismatch_on_different_classes
coder = YAMLColumn.new(Array)
assert_raises(SerializationTypeMismatch) do
coder = YAMLColumn.new("attr_name", Array)
error = assert_raises(SerializationTypeMismatch) do
coder.load "--- foo"
end
assert_equal %{Attribute `attr_name` was supposed to be a Array, but was a String. -- "foo"}, error.to_s
end
def test_nil_is_ok
coder = YAMLColumn.new
coder = YAMLColumn.new("attr_name")
assert_nil coder.load "--- "
end
def test_returns_new_with_different_class
coder = YAMLColumn.new SerializationTypeMismatch
coder = YAMLColumn.new("attr_name", SerializationTypeMismatch)
assert_equal SerializationTypeMismatch, coder.load("--- ").class
end
def test_returns_string_unless_starts_with_dash
coder = YAMLColumn.new
coder = YAMLColumn.new("attr_name")
assert_equal "foo", coder.load("foo")
end
def test_load_handles_other_classes
coder = YAMLColumn.new
coder = YAMLColumn.new("attr_name")
assert_equal [], coder.load([])
end
def test_load_doesnt_swallow_yaml_exceptions
coder = YAMLColumn.new
coder = YAMLColumn.new("attr_name")
bad_yaml = "--- {"
assert_raises(Psych::SyntaxError) do
coder.load(bad_yaml)
......@@ -52,7 +54,7 @@ def test_load_doesnt_swallow_yaml_exceptions
end
def test_load_doesnt_handle_undefined_class_or_module
coder = YAMLColumn.new
coder = YAMLColumn.new("attr_name")
missing_class_yaml = '--- !ruby/object:DoesNotExistAndShouldntEver {}\n'
assert_raises(ArgumentError) do
coder.load(missing_class_yaml)
......
......@@ -240,6 +240,20 @@ def test_regression_serialized_default_on_text_column_with_null_false
assert_equal [], light.long_state
end
def test_unexpected_serialized_type
Topic.serialize :content, Hash
topic = Topic.create!(content: { zomg: true })
Topic.serialize :content, Array
topic.reload
error = assert_raise(ActiveRecord::SerializationTypeMismatch) do
topic.content
end
expected = "Attribute `content` was supposed to be a Array, but was a Hash. -- {:zomg=>true}"
assert_equal expected, error.to_s
end
def test_serialized_column_should_unserialize_after_update_column
t = Topic.create(content: "first")
assert_equal("first", t.content)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册