Skip to content

Commit

Permalink
Merge pull request #47191 from serg-kovalev/fix/issue-46351-serialize…
Browse files Browse the repository at this point in the history
…-default

Respect Column default in Type::Serialized
  • Loading branch information
byroot committed Feb 22, 2023
2 parents ca6f2f1 + 695db7b commit 2c97993
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def serialize(attr_name, class_name_or_coder = Object, yaml: {}, **options)
end

cast_type = cast_type.subtype if Type::Serialized === cast_type
Type::Serialized.new(cast_type, coder)
Type::Serialized.new(cast_type, coder, default: columns_hash[attr_name.to_s]&.default)
end
end

Expand Down
5 changes: 3 additions & 2 deletions activerecord/lib/active_record/type/serialized.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ class Serialized < DelegateClass(ActiveModel::Type::Value) # :nodoc:

attr_reader :subtype, :coder

def initialize(subtype, coder)
def initialize(subtype, coder, default: nil)
@subtype = subtype
@coder = coder
@default = default
super(subtype)
end

Expand All @@ -25,7 +26,7 @@ def deserialize(value)

def serialize(value)
return if value.nil?
unless default_value?(value)
unless default_value?(value) && @default.nil?
super coder.dump(value)
end
end
Expand Down
37 changes: 37 additions & 0 deletions activerecord/test/cases/serialized_attribute_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,43 @@ def test_values_cast_from_nil_are_persisted_as_nil
assert_equal [topic, topic2], Topic.where(content: nil).sort_by(&:id)
end

# MySQL doesn't support default values for text columns, so we need to skip this test for MySQL
if !current_adapter?(:Mysql2Adapter)
def test_serialized_attribute_with_default_can_update_to_default
ActiveRecord::Schema.define do
create_table :tmp_posts, force: true do |t|
t.text :content, null: false, default: "{}"
end
end
klass = Class.new(ActiveRecord::Base) do
self.table_name = "tmp_posts"
serialize(:content, Hash)
end

t = klass.create!(content: { "other_key" => "new_value" })
assert_equal({ "other_key" => "new_value" }, t.content)

t.update!(content: {})
assert_equal({}, t.content)
end

def test_nil_is_always_persisted_as_default
ActiveRecord::Schema.define do
create_table :tmp_posts, force: true do |t|
t.text :content, null: false, default: "{}"
end
end
klass = Class.new(ActiveRecord::Base) do
self.table_name = "tmp_posts"
serialize(:content, Hash)
end

t = klass.create!(content: { foo: "bar" })
t.update_attribute :content, nil
assert_equal({}, t.content)
end
end

def test_nil_is_always_persisted_as_null
Topic.serialize(:content, Hash)

Expand Down

0 comments on commit 2c97993

Please sign in to comment.