Forum: Ruby What is that method called?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
David T. (Guest)
on 2008-11-11 11:19
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?
Clifford H. (Guest)
on 2008-11-11 12:00
(Received via mailing list)
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..
Peter S. (Guest)
on 2008-11-11 12:07
(Received via mailing list)
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/...

Cheers,
Peter
Mike Paul (Guest)
on 2008-11-11 12:13
(Received via mailing list)
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
David T. (Guest)
on 2008-11-11 12:49
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'... :)

Thanks for the replies!
Justin C. (Guest)
on 2008-11-11 13:15
(Received via mailing list)
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'... :)
>
> 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
Shot (Piotr S.) (Guest)
on 2008-11-11 14:25
(Received via mailing list)
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
Boris B. (Guest)
on 2008-11-11 16:32
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}..."
Brian A. (Guest)
on 2008-11-11 19:55
(Received via mailing list)
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
Brian A. (Guest)
on 2008-11-11 20:00
(Received via mailing list)
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
Boris B. (Guest)
on 2008-11-12 13:41
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
Brian A. (Guest)
on 2008-11-12 22:57
(Received via mailing list)
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
This topic is locked and can not be replied to.