I need the method that has the ability to turn a long string like this:
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Pellentesque
pulvinar turpis a nisi. Cras id elit. Aliquam vitae pede nec lacus
elementum lacinia. Ut aliquam vehicula sem.
into a shorter string like this:
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Pellentesque
pulvinar turpis…
My problem is that I can’t remember what the method is called. I looked
through the whole Ruby String documentation
(http://ruby-doc.org/core/classes/String.html) but I couldn’t find it.
Can anyone remember what it’s called?
I need the method that has the ability to turn a long string… into a shorter string…
My problem is that I can’t remember what the method is called. I looked
through the whole Ruby String documentation…
There’s no such method in Ruby. You might be thinking of the
truncate method that’s part of ActionView’s TextHelper module.
truncate method that’s part of ActionView’s TextHelper module.
truncate is what it’s called. I was actually searching for ‘rails
StringHelper’…
Thanks for the replies!
Also:
a_long_string = “Lorem ipsum dolor sit amet, consectetuer adipiscing
elit. Pellentesque pulvinar turpis a nisi. Cras id elit. Aliquam vitae
pede nec lacus elementum lacinia. Ut aliquam ehicula sem.”
limit = 86
a_long_string[0, limit] << “…” #=> “Lorem ipsum dolor sit amet,
consectetuer adipiscing elit. Pellentesque pulvinar turpis…”
string = <<END
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Pellentesque
pulvinar turpis a nisi. Cras id elit. Aliquam vitae pede nec lacus
elementum lacinia. Ut aliquam vehicula sem.
END
a_long_string = “Lorem ipsum dolor sit amet, consectetuer adipiscing
elit. Pellentesque pulvinar turpis a nisi. Cras id elit. Aliquam vitae
pede nec lacus elementum lacinia. Ut aliquam ehicula sem.”
limit = 86
a_long_string[0, limit] << “…” #=> “Lorem ipsum dolor sit amet,
consectetuer adipiscing elit. Pellentesque pulvinar turpis…”
In general, for input strings less than the limit, you wouldn’t want
“…”
class String
Return an ellided string no longer than total_length
“hello”.ellide(5) -> “hello”
“hello there”.ellide(8) -> “hello…”
def ellide total_length
if self.length > total_length
raise ‘total_length must be at least 3’ if total_length < 3
return self[0, total_length - 3] + ‘…’
else
return self
end
end
end
It is nicer to break at word boundaries in some contexts. But if it’s
a single word (such as a long email address), then you’d still want to
show something more than “…”. Maybe you can add a check for that.
a_long_string = “Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Pellentesque pulvinar turpis a nisi. Cras id elit. Aliquam vitae pede nec
lacus elementum lacinia. Ut aliquam ehicula sem.”
limit = 86
a_long_string[0, limit] << “…” #=> “Lorem ipsum dolor sit amet,
consectetuer adipiscing elit. Pellentesque pulvinar turpis…”
Note that in Ruby 1.8 String#[] doesn’t work on chars, but bytes,
which means the above is not reliable for multibyte strings like UTF-8:
polish = ‘W trosce o byt i przyszÅ‚ość naszej Ojczyzny’
=> “W trosce o byt i przyszÅ‚ość naszej Ojczyzny”
polish[0, 27]
=> “W trosce o byt i przyszÅ‚o\305”
polish[0, 30]
=> “W trosce o byt i przyszÅ‚ość”
In Ruby 1.9 String#[] works on chars, so the above works as expected:
polish = ‘W trosce o byt i przyszÅ‚ość naszej Ojczyzny’
=> “W trosce o byt i przyszÅ‚ość naszej Ojczyzny”
a single word (such as a long email address), then you’d still want to
end
That fixes the problem of showing only ‘…’, but now ‘puts
wordlist[0]’ may display more than the limit.
Refining your idea a bit gave the following:
def elide_words total_length
return self unless self.length > total_length
raise ‘total_length must be at least 3’ if total_length < 3
words = self.split(’ ')
result = ‘’
words.each do |word|
len = total_length - (result.empty? ? 3 : 4)
break if result.length + word.length > len
result << ’ ’ unless result.empty?
result << word
end
if result.empty?
return self.elide(total_length)
else
return result + ‘…’
end
end
But we really don’t need to find all the space boundaries via
split(), so the following version is about 10 times faster:
def elide_words total_length
return self unless self.length > total_length
raise ‘total_length must be at least 3’ if total_length < 3
len = total_length - 3 # room for ‘…’
# Case 1: natural word break
return self[0, len] + '...' if self[len,1] == ' '
# Case 2: search backward for a char preceding a delimiter
delim_found = false
idx = len.downto(0) {|i|
if delim_found
break (i + 1) if self[i,1] != ' '
else
delim_found = true if self[i,1] == ' '
end
}
return self[0, idx] + '...'
It is nicer to break at word boundaries in some contexts. But if it’s
a single word (such as a long email address), then you’d still want to
show something more than “…”. Maybe you can add a check for that.