Extracted String#truncate from TextHelper#truncate [DHH]

This commit is contained in:
David Heinemeier Hansson
2010-06-01 16:38:42 -05:00
parent ea037ff557
commit d57397c4b6
4 changed files with 69 additions and 11 deletions

View File

@@ -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 @@ module ActionView
# ==== 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 @@ module ActionView
# 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 @@ module ActionView
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

View File

@@ -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]

View File

@@ -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

View File

@@ -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