diff --git a/activerecord/lib/active_record/type/serialized.rb b/activerecord/lib/active_record/type/serialized.rb index a34b2fe702..2e4d2e0bf8 100644 --- a/activerecord/lib/active_record/type/serialized.rb +++ b/activerecord/lib/active_record/type/serialized.rb @@ -61,9 +61,12 @@ module ActiveRecord end def encoded(value) - unless default_value?(value) - coder.dump(value) + return if default_value?(value) + payload = coder.dump(value) + if payload && binary? + payload.force_encoding(Encoding::BINARY) end + payload end end end diff --git a/activerecord/test/cases/serialized_attribute_test.rb b/activerecord/test/cases/serialized_attribute_test.rb index a65a919975..19a6661f9e 100644 --- a/activerecord/test/cases/serialized_attribute_test.rb +++ b/activerecord/test/cases/serialized_attribute_test.rb @@ -4,6 +4,7 @@ require "cases/helper" require "models/person" require "models/traffic_light" require "models/post" +require "models/binary_field" class SerializedAttributeTest < ActiveRecord::TestCase fixtures :topics, :posts @@ -317,6 +318,20 @@ class SerializedAttributeTest < ActiveRecord::TestCase assert_equal({}, topic.content) end + if current_adapter?(:Mysql2Adapter) + def test_is_not_changed_when_stored_in_mysql_blob + value = %w(Fée) + model = BinaryField.create!(normal_blob: value, normal_text: value) + model.reload + + model.normal_text = value + assert_not_predicate model, :normal_text_changed? + + model.normal_blob = value + assert_not_predicate model, :normal_blob_changed? + end + end + def test_values_cast_from_nil_are_persisted_as_nil # This is required to fulfil the following contract, which must be universally # true in Active Record: diff --git a/activerecord/test/models/binary_field.rb b/activerecord/test/models/binary_field.rb new file mode 100644 index 0000000000..9032ae8075 --- /dev/null +++ b/activerecord/test/models/binary_field.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +class BinaryField < ActiveRecord::Base + serialize :normal_blob + serialize :normal_text +end