What is that method called?


#1

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?


#2

David T. wrote:

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.

Clifford H…


#3

I seriously doubt this is part of standard Ruby.

You have probably seen this in ActiveSupport and/or the ‘english’ gem

  • English::String#brief:

http://english.rubyforge.org/rdoc/classes/English/String.html#M000096

Cheers,
Peter


#4

Hi David - just done this in Agile Development

truncate(string, n) where string is the string to be shortened and n is
the
number of characters you want it shortened to.

Cheers
Mike


#5

Peter S. wrote:

I seriously doubt this is part of standard Ruby.

You’re right, it’s not a part of the Ruby standard library:

Clifford H. wrote:

There’s no such method in Ruby. You might be thinking of the
truncate method that’s part of ActionView’s TextHelper module.

truncate is what it’s called. I was actually searching for ‘rails
StringHelper’… :slight_smile:

Thanks for the replies!


#6

David T. wrote:

truncate method that’s part of ActionView’s TextHelper module.

truncate is what it’s called. I was actually searching for ‘rails
StringHelper’… :slight_smile:

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…”

-Justin


#7

perhaps this works?

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

lead = 90

wordlist = string.split(’ ')

shorttext = ‘’

for word in wordlist

break if(shorttext.length + word.length > lead)
shorttext = shorttext + word + " "

end

get rid of the last space

shorttext.chop!

puts “#{shorttext}…”


#8

Justin C. removed_email_address@domain.invalid writes:

Clifford H. wrote:

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…”

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


#9

Boris B. removed_email_address@domain.invalid writes:

wordlist = string.split(’ ')

get rid of the last space

shorttext.chop!

puts “#{shorttext}…”

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.

e.g. for string = ‘removed_email_address@domain.invalid’, lead = 15


#10

Justin C.:

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”

polish[0, 27]
=> “W trosce o byt i przyszÅ‚ość”

– Shot


#11

Boris B. removed_email_address@domain.invalid writes:

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] + '...'

end


#12

Brian A. wrote:

Boris B. removed_email_address@domain.invalid writes:

wordlist = string.split(’ ')

get rid of the last space

shorttext.chop!

puts “#{shorttext}…”

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.

e.g. for string = ‘removed_email_address@domain.invalid’, lead = 15

Hehe, ok:

if shorttext.empty?
puts wordlist[0]
else
puts “#{shorttext}…”
end