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

Merge pull request #29520 from kirs/serialize-vs-postgres-native-column

Do not let use `serialize` on native JSON/array column
This commit is contained in:
Sean Griffin 2017-08-04 18:05:00 -04:00 committed by GitHub
commit 978b3d604a
3 changed files with 42 additions and 0 deletions

View file

@ -5,6 +5,16 @@ module ActiveRecord
module Serialization
extend ActiveSupport::Concern
class ColumnNotSerializableError < StandardError
def initialize(name, type)
super <<-EOS.strip_heredoc
Column `#{name}` of type #{type.class} does not support `serialize` feature.
Usually it means that you are trying to use `serialize`
on a column that already implements serialization natively.
EOS
end
end
module ClassMethods
# If you have an attribute that needs to be saved to the database as an
# object, and retrieved as the same object, then specify the name of that
@ -60,9 +70,23 @@ module ActiveRecord
end
decorate_attribute_type(attr_name, :serialize) do |type|
if type_incompatible_with_serialize?(type)
raise ColumnNotSerializableError.new(attr_name, type)
end
Type::Serialized.new(type, coder)
end
end
private
def type_incompatible_with_serialize?(type)
type.is_a?(ActiveRecord::Type::Json) ||
(
defined?(ActiveRecord::ConnectionAdapters::PostgreSQL) &&
type.is_a?(ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Array)
)
end
end
end
end

View file

@ -47,6 +47,15 @@ class PostgresqlArrayTest < ActiveRecord::PostgreSQLTestCase
assert ratings_column.array?
end
def test_not_compatible_with_serialize
new_klass = Class.new(PgArray) do
serialize :tags, Array
end
assert_raises(ActiveRecord::AttributeMethods::Serialization::ColumnNotSerializableError) do
new_klass.new
end
end
def test_default
@connection.add_column "pg_arrays", "score", :integer, array: true, default: [4, 4, 2]
PgArray.reset_column_information

View file

@ -33,6 +33,15 @@ module PostgresqlJSONSharedTestCases
x.reload
assert_equal ["foo" => "bar"], x.objects
end
def test_not_compatible_with_serialize_macro
new_klass = Class.new(klass) do
serialize :payload, JSON
end
assert_raises(ActiveRecord::AttributeMethods::Serialization::ColumnNotSerializableError) do
new_klass.new
end
end
end
class PostgresqlJSONTest < ActiveRecord::PostgreSQLTestCase