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
|
module Serialization
|
||||||
extend ActiveSupport::Concern
|
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
|
module ClassMethods
|
||||||
# If you have an attribute that needs to be saved to the database as an
|
# 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
|
# object, and retrieved as the same object, then specify the name of that
|
||||||
|
@ -60,9 +70,23 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
decorate_attribute_type(attr_name, :serialize) do |type|
|
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)
|
Type::Serialized.new(type, coder)
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -47,6 +47,15 @@ class PostgresqlArrayTest < ActiveRecord::PostgreSQLTestCase
|
||||||
assert ratings_column.array?
|
assert ratings_column.array?
|
||||||
end
|
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
|
def test_default
|
||||||
@connection.add_column "pg_arrays", "score", :integer, array: true, default: [4, 4, 2]
|
@connection.add_column "pg_arrays", "score", :integer, array: true, default: [4, 4, 2]
|
||||||
PgArray.reset_column_information
|
PgArray.reset_column_information
|
||||||
|
|
|
@ -33,6 +33,15 @@ module PostgresqlJSONSharedTestCases
|
||||||
x.reload
|
x.reload
|
||||||
assert_equal ["foo" => "bar"], x.objects
|
assert_equal ["foo" => "bar"], x.objects
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
class PostgresqlJSONTest < ActiveRecord::PostgreSQLTestCase
|
class PostgresqlJSONTest < ActiveRecord::PostgreSQLTestCase
|
||||||
|
|
Loading…
Reference in a new issue