How to truncate text in Ruby on Rails

Posted on 14 August 2006

It's really simple to truncate text in Rails, just pass the function the text, the max number of characters you want to show and a truncate string you want to display instead of the last 3 characters.

truncate(category.description, 40, "...")

About Paul

Paul works for Kyan web design agency in Surrey, UK as a Ruby on Rails developer.

Follow Paul on Twitter

Email: paulsturgess [at] gmail.com

Read more articles in the archive →

Comments...

  • You'd probably be happier with something like this, which will cut off text at a word boundary. You can put it in your application helper to use it in all your views.

    def snippet(thought)

    wordcount = 10

    thought.split[0..(wordcount-1)].join(" ") + (thought.split.size > wordcount ? "..." : "")

    end

    Chris Kampmeier at 22 Jan 07 at 20:40

  • @Chris thanks, I'm gunna use this. However, I modified it so that the wordcount is passable as a parameter:


    def snippet(thought, wordcount)
    thought.split[0..(wordcount-1)].join(" ") +(thought.split.size > wordcount ? "..." : "")
    end

    Also, just an fyi, when I pasted your code into Textmate it preserved the fancy quotes, which gave me about 30 seconds of WTF?

    Byron Bowerman at 30 Nov 07 at 16:53

  • Try this one out, the number in brackets is the number of chars to match:

    thought.gsub(/^(.{10}[\w.]*)(.*)/) {$2.empty? ? $1 : $1 + '...'}

    It doesn't break words and adds '...' if necessary. Check out www.golark.com and click submit to really be impressed with the power of regex.

    lou at 06 Dec 07 at 21:42

  • Great, it took the asterisks out. Replace the a's in the following string with asterisks:

    thought.gsub(/^(.{10}[\w.]a)(.a)/) {$2.empty? ? $1 : $1 + '...'}

    lou at 06 Dec 07 at 21:46

  • Seems all of them to be more complicated than ...

    thought = (thought.length > wordcount) ? "#{thought[0..(wordcount - 1)] ..." : thought

    Sam_dal at 02 Dec 08 at 15:24

  • Odd that the Ruby String class doesn't have a method to truncate itself.

    Ed at 07 Dec 08 at 21:03

  • "1234567890"[0..4] => "12345"

    Simple is good at 09 Jan 09 at 07:45

  • “1234567890”.first(5)

    and there's also
    “1234567890”.last(5)

    The Irish Penguin at 14 Jan 09 at 04:50

  • @lou:

    Put an m after the second slash to truncate multiline text appropriately

    thought.gsub(/^(.{10}[\w.]a)(.a)/m) {$2.empty? ? $1 : $1 + ‘…’}

    nice at 07 Jul 09 at 15:09

  • This will be deprecated, you need to use

    truncate(text, :length => 123, :omission =>"...")

    Michael Hendrickx at 14 Aug 09 at 01:42

  • asgw3.txt;4;15

    asgw3.txt;4;15 at 16 Sep 09 at 22:00

  • asgw3.txt;4;15

    asgw3.txt;4;15 at 16 Sep 09 at 22:01

  • Thanks for the info and comments. Very useful

    cheers
    http://www.movieteca.com

    Fabian Pena at 14 Oct 09 at 21:19

  • <%=course.description.length > 60 ? course.description[0..60] << '...': course.description unless course.description.nil? %>

    This can be directly written in views ,which checks the length of description.

    je at 10 Feb 10 at 00:45

  • @je I think you are missing the point of the truncate method as it will do all that for you.

    Paul Sturgess at 10 Feb 10 at 03:03

  • It would be great if this worked on word boundaries, but still used a maximum number of chars for input. A lot of the comments don't seem to get that the point of this is to put on the "..." conditionally.

    French Vocabulary at 22 Feb 10 at 23:50

  • @French Vocabulary - The gsub method posted by lou above does what you are asking perfectly. Thanks lou!

    mvaski at 26 Nov 10 at 09:06

  • Hi, All. I know this is sort of an old post but I have come up with a long method to strip html tags from say, a description of an item, truncate it to 100 chars and omit the last word (it will more than likely be truncated to begin with)

    <% @truncated = truncate(strip_tags(item.description), :length => 100, :omission => "...")%>
    <% @wordcount = @truncated.scan(/\w+/).size%>
    <% @truncated.split(/\w+/) %>
    <% @truncated[@wordcount-2]=""%>
    <%= @truncated %>

    NOTE: This is in the view only, im sure it can be moved into the model.
    I know this is a long way of doing it, but if anyone can condense this or recommend something simpler, great!

    Matenia Rossides at 18 Dec 10 at 20:58

  • ok .. it stripped a few things, there is meant to be an at sign where the first truncated appears and also before wordcount-2

    Matenia Rossides at 18 Dec 10 at 21:02

  • Well just wanted to say that truncate helper method allows you to pass a :separator option so that will truncate to the nearest separator.
    Examples:

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

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

    Monomachus at 03 Jan 11 at 05:30

  • Nice post and comments, congrats!

    The regexp proposed above doesn't work well with non ascii chars. It can be easily fixed replacing [\w.]a with [^\s]a (everything but spaces, again replace the "a" with asterisk):

    thought.gsub(/^(.{10}[^\s]a)(.a)/m) {$2.empty? ? $1 : $1 + ‘…’}

    Nando at 27 Apr 11 at 13:05

  • You can actually do *much* better than that if you're willing to have your function take more than one line.

    Buena Vista at 15 Jul 11 at 11:05

Got something to say?