From 4dfdc7eb90be905e0e8e583f942091ce12381b37 Mon Sep 17 00:00:00 2001
From: Jordan Thomas <mail@jordanthomas.me>
Date: Fri, 26 Apr 2019 13:29:41 -0400
Subject: Frozen truncate (#36109)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* Add test asserting truncate returns unfrozen string

* Ensure strings returned from truncate are not frozen

This fixes an issue where strings too short to be truncated were
returned unfrozen, where as long-enough strings were returned
frozen. Now retuned strings will not be frozen whether or not
the string returned was shortened.

* Update changelog w/ new truncate behavior description

[Jordan Thomas + Rafael Mendonça França]
---
 activesupport/CHANGELOG.md                            | 19 +++++++++++++++++++
 .../lib/active_support/core_ext/string/filters.rb     |  2 +-
 activesupport/test/core_ext/string_ext_test.rb        |  5 +++++
 3 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index d1b3b31646..ccdf2c3040 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -1,3 +1,22 @@
+*   `truncate` would return the original string if it was too short to be truncated
+    and a frozen string if it were long enough to be truncated. Now truncate will
+    consistently return an unfrozen string regardless. This behavior is consistent
+    with `gsub` and `strip`.
 
+    Before:
+
+      'foobar'.truncate(5).frozen?
+      => true
+      'foobar'.truncate(6).frozen?
+      => false
+
+    After:
+
+      'foobar'.truncate(5).frozen?
+      => false
+      'foobar'.truncate(6).frozen?
+      => false
+
+    *Jordan Thomas*
 
 Please check [6-0-stable](https://github.com/rails/rails/blob/6-0-stable/activesupport/CHANGELOG.md) for previous changes.
diff --git a/activesupport/lib/active_support/core_ext/string/filters.rb b/activesupport/lib/active_support/core_ext/string/filters.rb
index df0e79afa8..7f28bd52f2 100644
--- a/activesupport/lib/active_support/core_ext/string/filters.rb
+++ b/activesupport/lib/active_support/core_ext/string/filters.rb
@@ -75,7 +75,7 @@ class String
         length_with_room_for_omission
       end
 
-    "#{self[0, stop]}#{omission}"
+    +"#{self[0, stop]}#{omission}"
   end
 
   # Truncates +text+ to at most <tt>bytesize</tt> bytes in length without
diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb
index 4ffa33aa61..c5a000b67a 100644
--- a/activesupport/test/core_ext/string_ext_test.rb
+++ b/activesupport/test/core_ext/string_ext_test.rb
@@ -291,6 +291,11 @@ class StringInflectionsTest < ActiveSupport::TestCase
     assert_equal "Hello Big[...]", "Hello Big World!".truncate(15, omission: "[...]", separator: /\s/)
   end
 
+  def test_truncate_returns_frozen_string
+    assert_not "Hello World!".truncate(12).frozen?
+    assert_not "Hello World!!".truncate(12).frozen?
+  end
+
   def test_truncate_bytes
     assert_equal "πŸ‘πŸ‘πŸ‘πŸ‘", "πŸ‘πŸ‘πŸ‘πŸ‘".truncate_bytes(16)
     assert_equal "πŸ‘πŸ‘πŸ‘πŸ‘", "πŸ‘πŸ‘πŸ‘πŸ‘".truncate_bytes(16, omission: nil)
-- 
cgit v1.2.3