Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Extracted String#truncate from TextHelper#truncate [DHH]

  • Loading branch information...
commit bd7a27ac6b64c2ec46a90176c7d6d7477b030a82 1 parent 19d1d42
David Heinemeier Hansson dhh authored mikel committed
16 actionpack/lib/action_view/helpers/text_helper.rb
View
@@ -1,4 +1,5 @@
require 'active_support/core_ext/object/blank'
+require 'active_support/core_ext/string/filters'
require 'action_view/helpers/tag_helper'
module ActionView
@@ -42,7 +43,7 @@ def safe_concat(string)
# ==== Examples
#
# truncate("Once upon a time in a world far far away")
- # # => Once upon a time in a world...
+ # # => Once upon a time in a worl...
#
# truncate("Once upon a time in a world far far away", :separator => ' ')
# # => Once upon a time in a world...
@@ -50,9 +51,6 @@ def safe_concat(string)
# truncate("Once upon a time in a world far far away", :length => 14)
# # => Once upon a...
#
- # truncate("And they found that many people were sleeping better.", :length => 25, "(clipped)")
- # # => And they found t(clipped)
- #
# truncate("And they found that many people were sleeping better.", :omission => "... (continued)", :length => 25)
# # => And they f... (continued)
#
@@ -73,14 +71,10 @@ def truncate(text, *args)
options[:length] = args[0] || 30
options[:omission] = args[1] || "..."
end
- options.reverse_merge!(:length => 30, :omission => "...")
- if text
- l = options[:length] - options[:omission].mb_chars.length
- chars = text.mb_chars
- stop = options[:separator] ? (chars.rindex(options[:separator].mb_chars, l) || l) : l
- (chars.length > options[:length] ? chars[0...stop] + options[:omission] : text).to_s
- end
+ options.reverse_merge!(:length => 30)
+
+ text.truncate(options.delete(:length), options) if text
end
# Highlights one or more +phrases+ everywhere in +text+ by inserting it into
2  activesupport/CHANGELOG
View
@@ -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]
33 activesupport/lib/active_support/core_ext/string/filters.rb
View
@@ -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 @@ def squish!
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
29 activesupport/test/core_ext/string_ext_test.rb
View
@@ -210,6 +210,35 @@ def test_string_squish
# 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
Please sign in to comment.
Something went wrong with that request. Please try again.