Skip to content

Commit 7a031e3

Browse files
authored
Merge pull request rails#54683 from byroot/column-default-deserialize
Don't deserialize mutable defaults
2 parents 3eb5f34 + 205cdd5 commit 7a031e3

File tree

9 files changed

+22
-15
lines changed

9 files changed

+22
-15
lines changed

activerecord/lib/active_record/attributes.rb

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -244,10 +244,7 @@ def _default_attributes # :nodoc:
244244
# TODO: Remove the need for a connection after we release 8.1.
245245
attributes_hash = with_connection do |connection|
246246
columns_hash.transform_values do |column|
247-
type = type_for_column(connection, column)
248-
default = column.default
249-
default = type.deserialize(default) unless default.nil?
250-
ActiveModel::Attribute.from_database(column.name, default, type)
247+
ActiveModel::Attribute.from_database(column.name, column.default, type_for_column(connection, column))
251248
end
252249
end
253250

activerecord/lib/active_record/connection_adapters/column.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def initialize(name, cast_type, default, sql_type_metadata = nil, null = true, d
2222
@cast_type = cast_type
2323
@sql_type_metadata = sql_type_metadata
2424
@null = null
25-
@default = default
25+
@default = default.nil? || cast_type.mutable? ? default : cast_type.deserialize(default)
2626
@default_function = default_function
2727
@collation = collation
2828
@comment = comment
@@ -117,7 +117,7 @@ def virtual?
117117
def deduplicated
118118
@name = -name
119119
@sql_type_metadata = sql_type_metadata.deduplicate if sql_type_metadata
120-
@default = -default if default
120+
@default = -default if String === default
121121
@default_function = -default_function if default_function
122122
@collation = -collation if collation
123123
@comment = -comment if comment

activerecord/test/cases/adapters/postgresql/geometric_test.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,11 +131,11 @@ def test_legacy_column
131131
end
132132

133133
def test_legacy_default
134-
assert_equal ActiveRecord::Point.new(12.2, 13.3), PostgresqlPoint.column_defaults["legacy_y"]
135-
assert_equal ActiveRecord::Point.new(12.2, 13.3), PostgresqlPoint.new.legacy_y
134+
assert_equal [12.2, 13.3], PostgresqlPoint.column_defaults["legacy_y"]
135+
assert_equal [12.2, 13.3], PostgresqlPoint.new.legacy_y
136136

137-
assert_equal ActiveRecord::Point.new(14.4, 15.5), PostgresqlPoint.column_defaults["legacy_z"]
138-
assert_equal ActiveRecord::Point.new(14.4, 15.5), PostgresqlPoint.new.legacy_z
137+
assert_equal [14.4, 15.5], PostgresqlPoint.column_defaults["legacy_z"]
138+
assert_equal [14.4, 15.5], PostgresqlPoint.new.legacy_z
139139
end
140140

141141
def test_legacy_schema_dumping

activerecord/test/cases/adapters/postgresql/json_test.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ def setup
1010
super
1111
@connection.create_table("json_data_type") do |t|
1212
t.public_send column_type, "payload", default: {} # t.json 'payload', default: {}
13+
t.public_send column_type, "with_defaults", default: { list: [] }
1314
t.public_send column_type, "settings" # t.json 'settings'
1415
t.public_send column_type, "objects", array: true # t.json 'objects', array: true
1516
end
@@ -25,6 +26,10 @@ def test_default
2526
assert_equal({ "users" => "read", "posts" => ["read", "write"] }, klass.new.permissions)
2627
end
2728

29+
def test_default_before_type_cast
30+
assert_equal '{"list":[]}', klass.new.with_defaults_before_type_cast.gsub(" ", "")
31+
end
32+
2833
def test_deserialize_with_array
2934
x = klass.new(objects: ["foo" => "bar"])
3035
assert_equal ["foo" => "bar"], x.objects

activerecord/test/cases/adapters/sqlite3/json_test.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ def setup
1010
super
1111
@connection.create_table("json_data_type") do |t|
1212
t.json "payload", default: {}
13+
t.json "with_defaults", default: { list: [] }
1314
t.json "settings"
1415
end
1516
end
@@ -22,6 +23,10 @@ def test_default
2223
assert_equal({ "users" => "read", "posts" => ["read", "write"] }, klass.new.permissions)
2324
end
2425

26+
def test_default_before_type_cast
27+
assert_equal '{"list":[]}', klass.new.with_defaults_before_type_cast
28+
end
29+
2530
private
2631
def column_type
2732
:json

activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -636,7 +636,7 @@ def test_columns_with_default
636636
column = @conn.columns("ex").find { |x|
637637
x.name == "number"
638638
}
639-
assert_equal "10", column.default
639+
assert_equal 10, column.default
640640
end
641641
end
642642

activerecord/test/cases/migration/change_schema_test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def test_create_table_with_defaults
7272
assert_equal "hello", one.default
7373
assert_equal true, two.fetch_cast_type(connection).deserialize(two.default)
7474
assert_equal false, three.fetch_cast_type(connection).deserialize(three.default)
75-
assert_equal "1", four.default
75+
assert_equal 1, four.default
7676
assert_equal "hello", five.default unless mysql
7777
end
7878

activerecord/test/cases/migration/columns_test.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,13 @@ def test_rename_column_preserves_default_value_not_null
5555
add_column "test_models", "salary", :integer, default: 70000
5656

5757
default_before = connection.columns("test_models").find { |c| c.name == "salary" }.default
58-
assert_equal "70000", default_before
58+
assert_equal 70000, default_before
5959

6060
rename_column "test_models", "salary", "annual_salary"
6161

6262
assert_includes TestModel.column_names, "annual_salary"
6363
default_after = connection.columns("test_models").find { |c| c.name == "annual_salary" }.default
64-
assert_equal "70000", default_after
64+
assert_equal 70000, default_after
6565
end
6666

6767
if current_adapter?(:Mysql2Adapter, :TrilogyAdapter)

activerecord/test/cases/migration_test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1254,7 +1254,7 @@ def test_adding_multiple_columns
12541254

12551255
assert_equal 8, columns.size
12561256
[:name, :qualification, :experience].each { |s| assert_equal :string, column(s).type }
1257-
assert_equal "0", column(:age).default
1257+
assert_equal 0, column(:age).default
12581258
assert_equal "This is a comment", column(:birthdate).comment
12591259
end
12601260

0 commit comments

Comments
 (0)