views:

202

answers:

4

Does anybody have any code handy that center truncates a string in Ruby on Rails?

Something like this: Ex: "Hello World, how are you?" => "Hel...you?"

+5  A: 

Since you didn't specify how many characters you want to truncate, I'll assume (from your example) that you want to truncate strings whose length is greater than six. You can then use something like this:

s = "Hello World, how are you?"
s = s[0, 3] + "..." + s[-3, 3] if s.length > 9
=> "Hel...ou?"

Just adapt the ranges if you need to truncate more characters.

JG
DigitalRoss is right about the "> 9" instead of "> 6" -- if you have a String of length 7 then you've added two characters _and_ lost information.
James A. Rosen
You are right, forgot to count the size of the ellipsis. It's fixed now.
JG
+4  A: 

Here is my suggestion:

s[3...-4] = "..." if s.length > 9
DigitalRoss
I don't really like the editing-in-place since you don't know where the string is coming from. What if it's a model attribute and you later call save?
James A. Rosen
Yes, `(s=s.dup)[3...-4] = ...` might be better, and even functional in a "as a black box" viewpoint. Good point.
DigitalRoss
You probably meant (t=s.dup)... there
glenn jackman
Not really, it avoids modifying the underlying object, and now s is a reference to the new object. Now, if s was really thing.s, OK, now I agree with you, bad idea.
DigitalRoss
That is, it makes no difference which reference we assign to the object. s="abc";q=s;s[1]='x';q => "axc" # so we might as well reuse s
DigitalRoss
+10  A: 

How about a Regex version:

class String
  def ellipsisize
    gsub(/(...).{4,}(...)/, '\1...\2')
  end
end

"abc".ellipsisize #=> "abc"
"abcdefghi".ellipsisize #=> "abcdefghi"
"abcdefghij".ellipsisize #=> "abc...hij"

EDIT: as suggested in the comments, parameterised length (and using a different Regex notation, just for the heck of it)

class String
  def ellipsisize(len = 9)
    len = 9 unless len > 9 # assumes minimum chars at each end = 3
    gsub(%r{(...).{#{len-5},}(...)}, '\1...\2')
  end
end

so...

"abcdefghij".ellipsisize #=> "abc...hij"

but we can also:

"abcdefghij".ellipsisize(10) #=> "abcdefghij"
Mike Woodhouse
This solves the issues with both DigitalRoss's and JG's solutions. +1
James A. Rosen
Very nice, though I would have upvoted it just for the name of the method.
Telemachus
Cool, though it's gonna be better if you can modify it to accept string length parameter to apply the truncate only if the string is longer than that length.
khelll
+2  A: 

Here is a modified version of Mike Woodhouse's answer. It takes 2 optional params: a minimum length for the the string to be ellipsisized and the edge length.

class String
  def ellipsisize(minimum_length=4,edge_length=3)
    return self if self.length < minimum_length or self.length <= edge_length*2 
    edge = '.'*edge_length    
    mid_length = self.length - edge_length*2
    gsub(/(#{edge}).{#{mid_length},}(#{edge})/, '\1...\2')
  end
end


"abc".ellipsisize #=> "abc"
"abcdefghi".ellipsisize #=> "abcdefghi"
"abcdefghij".ellipsisize #=> "abc...hij"
"abcdefghij".ellipsisize(4,4) #=> "abcd...ghij"
"Testing all paramas and checking them!".ellipsisize(6,5) #=> "Testi...them!"
khelll
Duh, I changed mine then noticed you'd done a more complete version. Nice. +1
Mike Woodhouse
May be we should submit it as a patch to Rails team?
khelll