Truncate string with Rails?

I want to truncate a string as follows:

input:

string = "abcd asfsa sadfsaf safsdaf aaaaaaaaaa aaaaaaaaaa dddddddddddddd"

output:

string = "abcd asfsa sadfsaf safsdaf aa...ddddd"

Take a look at truncate, it partially does want you want. If you test whether it got trunctated or not, you could add some of the last part back after the truncated part.

truncate("Once upon a time in a world far far away")
# => "Once upon a time in a world..."

truncate("Once upon a time in a world far far away", :length => 17)
# => "Once upon a ti..."

truncate("Once upon a time in a world far far away", :length => 17, :separator => ' ')
# => "Once upon a..."

truncate("And they found that many people were sleeping better.", :length => 25, :omission => '... (continued)')
# => "And they f... (continued)"

You can do almost the same without Rails:

text.gsub(/^(.{50,}?).*$/m,'\1...')

50 is the length you need.


In the simplest case:

string = "abcd asfsa sadfsaf safsdaf aaaaaaaaaa aaaaaaaaaa dddddddddddddd"
tr_string = string[0, 20] + "..." + string[-5,5]

or

def trancate(string, length = 20)
  string.size > length+5 ? [string[0,length],string[-5,5]].join("...") : string
end

# Usage
trancate "abcd asfsa sadfsaf safsdaf aaaaaaaaaa aaaaaaaaaa dddddddddddddd"
#=> "abcd asfsa sadfsaf s...ddddd"
trancate "Hello Beautiful World"
#=> "Hello Beautiful World"
trancate "Hello Beautiful World", 5
#=> "Hello...World"

Truncate with Custom Omission

Similar to what some others have suggested here, you can use Rails' #truncate method and use a custom omission that is actually the last part of your string:

string = "abcd asfsa sadfsaf safsdaf aaaaaaaaaa aaaaaaaaaa dddddddddddddd"

truncate(string, length: 37, omission: "...#{string[-5, 5]}")
# => "abcd asfsa sadfsaf safsdaf aa...ddddd"

Exactly what you wanted.

Bonus Points

You might want to wrap this up in a custom method called something like truncate_middle that does some fancy footwork for you:

# Truncate the given string but show the last five characters at the end.
#
def truncate_middle( string, options = {} )
  options[:omission] = "...#{string[-5, 5]}"    # Use last 5 chars of string.

  truncate( string, options )
end

And then just call it like so:

string = "abcd asfsa sadfsaf safsdaf aaaaaaaaaa aaaaaaaaaa dddddddddddddd"

truncate_middle( string, length: 37 )
# => "abcd asfsa sadfsaf safsdaf aa...ddddd"

Boom!

Thanks for asking about this. I think it's a useful way to show a snippet of a longer piece of text.


This may not be the exact solution to your problem, but I think it will help put you in the right direction, with a pretty clean way of doing things.

If you want "Hello, World!" to be limited to the first five letters, you can do:

str = "Hello, World!"
str[0...5] # => "Hello"

If you want an ellipses, just interpolate it:

"#{str[0...5]}..." #=> "Hello..."