diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md index b68b029ecf..e7d77f22e4 100644 --- a/activemodel/CHANGELOG.md +++ b/activemodel/CHANGELOG.md @@ -1,3 +1,10 @@ +* The original string assigned to a model attribute is no longer incorrectly + frozen. + + Fixes #24185, #28718. + + *Matthew Draper* + * Avoid converting integer as a string into float. *namusyaka* diff --git a/activemodel/lib/active_model/type/string.rb b/activemodel/lib/active_model/type/string.rb index 8a91410998..850cab962b 100644 --- a/activemodel/lib/active_model/type/string.rb +++ b/activemodel/lib/active_model/type/string.rb @@ -11,9 +11,14 @@ module ActiveModel private - def cast_value(value) - ::String.new(super) - end + def cast_value(value) + case value + when ::String then ::String.new(value) + when true then "t".freeze + when false then "f".freeze + else value.to_s + end + end end end end diff --git a/activemodel/test/cases/type/string_test.rb b/activemodel/test/cases/type/string_test.rb index 7b25a1ef74..5d024089d0 100644 --- a/activemodel/test/cases/type/string_test.rb +++ b/activemodel/test/cases/type/string_test.rb @@ -10,6 +10,18 @@ module ActiveModel assert_equal "123", type.cast(123) end + test "cast strings are mutable" do + type = Type::String.new + + s = "foo" + assert_equal false, type.cast(s).frozen? + assert_equal false, s.frozen? + + f = "foo".freeze + assert_equal false, type.cast(f).frozen? + assert_equal true, f.frozen? + end + test "immutable strings are not duped coming out" do s = "foo" type = Type::ImmutableString.new @@ -18,10 +30,13 @@ module ActiveModel end test "values are duped coming out" do - s = "foo" type = Type::String.new + + s = "foo" assert_not_same s, type.cast(s) + assert_equal s, type.cast(s) assert_not_same s, type.deserialize(s) + assert_equal s, type.deserialize(s) end end end