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:
commit
978b3d604a
3 changed files with 42 additions and 0 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue