Truncate string with Rails?

若如初见. 提交于 2019-12-02 17:23:24
Veger

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)"

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"

You can do almost the same without Rails:

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

50 is the length you need.

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..."

This is the source code of String#truncate

def truncate(truncate_at, options = {})
  return dup unless length > truncate_at

  options[:omission] ||= '...'
  length_with_room_for_omission = truncate_at - options[:omission].length
  stop = \
    if options[:separator]
      rindex(options[:separator], length_with_room_for_omission) ||      length_with_room_for_omission
    else
      length_with_room_for_omission
    end

   "#{self[0...stop]}#{options[:omission]}"
end

So, as for you case

string.truncate(37, :omission => "...ddddd")

That's actually an interesting problem and you may want to solve it using javascript rather than ruby. Here is why, you're probably displaying this text on the screen somewhere, and you only have a certain amount of width available. So rather than having your link (or whatever text) cut down to a number of characters, what you really want is to make sure the text you're displaying never exceeds a certain width. How many characters can fit in a certain width depends on the font, spacing etc. (the css styles) you're using. You can make sure everything is ok if you're using a ruby-based solution, but it might all fall appart if you decide to change your styling later on.

So, I recommend a javascript-based solution. The way I've handled it previously has been to use the jquery truncate plugin. Include the plugin in your app. And then hook in some javascript similar to the following every time the page loads:

function truncateLongText() {
  $('.my_style1').truncate({
    width: 270,
    addtitle: true
  });
  $('.my_style2').truncate({
    width: 100
  });
}

Add in whatever other styles need to be truncatable and the width that they should respect, the plugin does the rest. This has the added advantage of having all your truncation logic for the whole app in one place which can be handy.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!