aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport
diff options
context:
space:
mode:
Diffstat (limited to 'activesupport')
-rw-r--r--activesupport/CHANGELOG2
-rw-r--r--activesupport/lib/active_support/core_ext/string/filters.rb33
-rw-r--r--activesupport/test/core_ext/string_ext_test.rb29
3 files changed, 64 insertions, 0 deletions
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG
index 0a25ad0406..d853788e00 100644
--- a/activesupport/CHANGELOG
+++ b/activesupport/CHANGELOG
@@ -1,5 +1,7 @@
*Rails 3.0.0 [beta 4/release candidate] (unreleased)*
+* Extracted String#truncate from TextHelper#truncate [DHH]
+
* Ruby 1.9: support UTF-8 case folding. #4595 [Norman Clarke]
* Renames Array#rand -> Array#random_element. [Santiago Pastorino, Rizwan Reza]
diff --git a/activesupport/lib/active_support/core_ext/string/filters.rb b/activesupport/lib/active_support/core_ext/string/filters.rb
index 6fda7efef5..cdd86a836f 100644
--- a/activesupport/lib/active_support/core_ext/string/filters.rb
+++ b/activesupport/lib/active_support/core_ext/string/filters.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/string/multibyte'
+
class String
# Returns the string, first removing all whitespace on both ends of
# the string, and then changing remaining consecutive whitespace
@@ -17,4 +19,35 @@ class String
gsub!(/\s+/, ' ')
self
end
+
+ # Truncates a given +text+ after a given <tt>length</tt> if +text+ is longer than <tt>length</tt>.
+ # The last characters will be replaced with the <tt>:omission</tt> (defaults to "...")
+ # for a total length not exceeding <tt>:length</tt>.
+ #
+ # Pass a <tt>:separator</tt> to truncate +text+ at a natural break.
+ #
+ # ==== Examples
+ #
+ # "Once upon a time in a world far far away".truncate(30)
+ # # => Once upon a time in a worl...
+ #
+ # "Once upon a time in a world far far away".truncate(30, :separator => ' ')
+ # # => Once upon a time in a world...
+ #
+ # "Once upon a time in a world far far away".truncate(14)
+ # # => Once upon a...
+ #
+ # "And they found that many people were sleeping better.".truncate(25, :omission => "... (continued)")
+ # # => And they f... (continued)
+ def truncate(length, options = {})
+ text = self.dup
+ options[:omission] ||= "..."
+
+ length_with_room_for_omission = length - options[:omission].mb_chars.length
+ chars = text.mb_chars
+ stop = options[:separator] ?
+ (chars.rindex(options[:separator].mb_chars, length_with_room_for_omission) || length_with_room_for_omission) : length_with_room_for_omission
+
+ (chars.length > length ? chars[0...stop] + options[:omission] : text).to_s
+ end
end
diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb
index 759b0ddcd6..d9702dd9ff 100644
--- a/activesupport/test/core_ext/string_ext_test.rb
+++ b/activesupport/test/core_ext/string_ext_test.rb
@@ -210,6 +210,35 @@ class StringInflectionsTest < Test::Unit::TestCase
# And changes the original string:
assert_equal original, expected
end
+
+ def test_truncate
+ assert_equal "Hello World!", "Hello World!".truncate(12)
+ assert_equal "Hello Wor...", "Hello World!!".truncate(12)
+ end
+
+ def test_truncate_with_omission_and_seperator
+ assert_equal "Hello[...]", "Hello World!".truncate(10, :omission => "[...]")
+ assert_equal "Hello[...]", "Hello Big World!".truncate(13, :omission => "[...]", :separator => ' ')
+ assert_equal "Hello Big[...]", "Hello Big World!".truncate(14, :omission => "[...]", :separator => ' ')
+ assert_equal "Hello Big[...]", "Hello Big World!".truncate(15, :omission => "[...]", :separator => ' ')
+ end
+
+ if RUBY_VERSION < '1.9.0'
+ def test_truncate_multibyte
+ with_kcode 'none' do
+ assert_equal "\354\225\210\353\205\225\355...", "\354\225\210\353\205\225\355\225\230\354\204\270\354\232\224".truncate(10)
+ end
+ with_kcode 'u' do
+ assert_equal "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 ...",
+ "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 \354\225\204\353\235\274\353\246\254\354\230\244".truncate(10)
+ end
+ end
+ else
+ def test_truncate_multibyte
+ assert_equal "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 ...".force_encoding('UTF-8'),
+ "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 \354\225\204\353\235\274\353\246\254\354\230\244".force_encoding('UTF-8').truncate(10)
+ end
+ end
end
class StringBehaviourTest < Test::Unit::TestCase