Module: ActionView::Helpers::TextHelper

Defined in:
lib/action_view/helpers/text_helper.rb

Overview

Provides a set of methods for working with text strings that can help unburden the level of inline Ruby code in the templates. In the example below we iterate over a collection of posts provided to the template and print each title after making sure it doesn't run longer than 20 characters:

<% for post in @posts %>
  Title: <%= truncate(post.title, 20) %>
<% end %>

Defined Under Namespace

Classes: Cycle

Constant Summary collapse

VERBOTEN_TAGS =
%w(form script)
VERBOTEN_ATTRS =
/^on/i
/
 (                       # leading text
   <\w+.*?>|             #   leading HTML tag, or
   [^=!:'"\/]|           #   leading punctuation, or 
   ^                     #   beginning of line
 )
 (
   (?:http[s]?:\/\/)|    # protocol spec, or
   (?:www\.)             # www.*
 ) 
 (
   ([\w]+[=?&\/.-]?)*    # url segment
   \w+[\/]?              # url tail
   (?:\#\w*)?            # trailing anchor
 )
 ([[:punct:]]|\s|<|$)    # trailing text
/x

Instance Method Summary collapse

Instance Method Details

Turns all urls and email addresses into clickable links. The link parameter can limit what should be linked. Options are :all (default), :email_addresses, and :urls.

Example:

auto_link("Go to http://www.rubyonrails.com and say hello to [email protected]com") =>
  Go to <a href="http://www.rubyonrails.com">http://www.rubyonrails.com</a> and
  say hello to <a href="mailto:[email protected]">[email protected]</a>

138
139
140
141
142
143
144
# File 'lib/action_view/helpers/text_helper.rb', line 138

def auto_link(text, link = :all, href_options = {})
  case link
    when :all             then auto_link_urls(auto_link_email_addresses(text), href_options)
    when :email_addresses then auto_link_email_addresses(text)
    when :urls            then auto_link_urls(text, href_options)
  end
end

#concat(string, binding) ⇒ Object

The regular puts and print are outlawed in eRuby. It's recommended to use the <%= “hello” %> form instead of print “hello”. If you absolutely must use a method-based output, you can use concat. It's used like this: <% concat “hello”, binding %>. Notice that it doesn't have an equal sign in front. Using <%= concat “hello” %> would result in a double hello.


15
16
17
# File 'lib/action_view/helpers/text_helper.rb', line 15

def concat(string, binding)
  eval("_erbout", binding).concat(string)
end

#cycle(first_value, *values) ⇒ Object

Returns a Cycle object whose to_s value cycles through items of an array every time it is called. This can be used to alternate classes for table rows:

<%- for item in @items do -%>

<tr class="<%= cycle("even", "odd") %>">
  ... use item ...
</tr>

<%- end -%>

You can use named cycles to prevent clashes in nested loops. You'll have to reset the inner cycle, manually:

<%- for item in @items do -%>

<tr class="<%= cycle("even", "odd", :name => "row_class")
  <td>
    <%- for value in item.values do -%>
      <span style="color:'<%= cycle("red", "green", "blue"
                                    :name => "colors") %>'">
        item
      </span>
    <%- end -%>
    <%- reset_cycle("colors") -%>
  </td>
</tr>

<%- end -%>


231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/action_view/helpers/text_helper.rb', line 231

def cycle(first_value, *values)
  if (values.last.instance_of? Hash)
    params = values.pop
    name = params[:name]
  else
    name = "default"
  end
  values.unshift(first_value)

  cycle = get_cycle(name)
  if (cycle.nil? || cycle.values != values)
    cycle = set_cycle(name, Cycle.new(*values))
  end
  return cycle.to_s
end

#excerpt(text, phrase, radius = 100, excerpt_string = "...") ⇒ Object

Extracts an excerpt from the text surrounding the phrase with a number of characters on each side determined by radius. If the phrase isn't found, nil is returned. Ex:

excerpt("hello my world", "my", 3) => "...lo my wo..."

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/action_view/helpers/text_helper.rb', line 44

def excerpt(text, phrase, radius = 100, excerpt_string = "...")
  if text.nil? || phrase.nil? then return end
  phrase = Regexp.escape(phrase)

  if found_pos = text =~ /(#{phrase})/i
    start_pos = [ found_pos - radius, 0 ].max
    end_pos   = [ found_pos + phrase.length + radius, text.length ].min

    prefix  = start_pos > 0 ? excerpt_string : ""
    postfix = end_pos < text.length ? excerpt_string : ""

    prefix + text[start_pos..end_pos].strip + postfix
  else
    nil
  end
end

#highlight(text, phrase, highlighter = '<strong class="highlight">\1</strong>') ⇒ Object

Highlights the phrase where it is found in the text by surrounding it like <strong class=“highlight”>I'm a highlight phrase</strong>. The highlighter can be specialized by passing highlighter as single-quoted string with 1 where the phrase is supposed to be inserted. N.B.: The phrase is sanitized to include only letters, digits, and spaces before use.


36
37
38
39
# File 'lib/action_view/helpers/text_helper.rb', line 36

def highlight(text, phrase, highlighter = '<strong class="highlight">\1</strong>')
  if phrase.blank? then return text end
  text.gsub(/(#{Regexp.escape(phrase)})/i, highlighter) unless text.nil?
end

#pluralize(count, singular, plural = nil) ⇒ Object

Attempts to pluralize the singular word unless count is 1. See source for pluralization rules.


62
63
64
65
66
67
68
69
70
71
72
# File 'lib/action_view/helpers/text_helper.rb', line 62

def pluralize(count, singular, plural = nil)
   "#{count} " + if count == 1
    singular
  elsif plural
    plural
  elsif Object.const_defined?("Inflector")
    Inflector.pluralize(singular)
  else
    singular + "s"
  end
end

#reset_cycle(name = "default") ⇒ Object

Resets a cycle so that it starts from the first element in the array the next time it is used.


249
250
251
252
253
# File 'lib/action_view/helpers/text_helper.rb', line 249

def reset_cycle(name = "default")
  cycle = get_cycle(name)
  return if cycle.nil?
  cycle.reset
end

#sanitize(html) ⇒ Object

Sanitizes the given HTML by making form and script tags into regular text, and removing all “onxxx” attributes (so that arbitrary Javascript cannot be executed). Also removes href attributes that start with “javascript:”.

Returns the sanitized text.


173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/action_view/helpers/text_helper.rb', line 173

def sanitize(html)
  # only do this if absolutely necessary
  if html.index("<")
    tokenizer = HTML::Tokenizer.new(html)
    new_text = ""

    while token = tokenizer.next
      node = HTML::Node.parse(nil, 0, 0, token, false)
      new_text << case node
        when HTML::Tag
          if VERBOTEN_TAGS.include?(node.name)
            node.to_s.gsub(/</, "&lt;")
          else
            if node.closing != :close
              node.attributes.delete_if { |attr,v| attr =~ VERBOTEN_ATTRS }
              if node.attributes["href"] =~ /^javascript:/i
                node.attributes.delete "href"
              end
            end
            node.to_s
          end
        else
          node.to_s.gsub(/</, "&lt;")
      end
    end

    html = new_text
  end

  html
end

#simple_format(text) ⇒ Object

Returns text transformed into HTML using very simple formatting rules Surrounds paragraphs with &lt;p&gt; tags, and converts line breaks into &lt;br /&gt; Two consecutive newlines(\n\n) are considered as a paragraph, one newline (\n) is considered a linebreak, three or more consecutive newlines are turned into two newlines


122
123
124
125
126
127
128
129
# File 'lib/action_view/helpers/text_helper.rb', line 122

def simple_format(text)
  text.gsub!(/(\r\n|\n|\r)/, "\n") # lets make them newlines crossplatform
  text.gsub!(/\n\n+/, "\n\n") # zap dupes
  text.gsub!(/\n\n/, '</p>\0<p>') # turn two newlines into paragraph
  text.gsub!(/([^\n])(\n)([^\n])/, '\1\2<br />\3') # turn single newline into <br />
  
  ("p", text)
end

Turns all links into words, like “<a href=”something“>else</a>” to “else”.


147
148
149
# File 'lib/action_view/helpers/text_helper.rb', line 147

def strip_links(text)
  text.gsub(/<a.*>(.*)<\/a>/m, '\1')
end

#truncate(text, length = 30, truncate_string = "...") ⇒ Object

Truncates text to the length of length and replaces the last three characters with the truncate_string if the text is longer than length.


21
22
23
24
25
26
27
28
29
30
# File 'lib/action_view/helpers/text_helper.rb', line 21

def truncate(text, length = 30, truncate_string = "...")
  if text.nil? then return end

  if $KCODE == "NONE"
    text.length > length ? text[0..(length - 3)] + truncate_string : text
  else
    chars = text.split(//)
    chars.length > length ? chars[0..(length-3)].join + truncate_string : text
  end
end

#word_wrap(text, line_width = 80) ⇒ Object

Word wrap long lines to line_width.


75
76
77
# File 'lib/action_view/helpers/text_helper.rb', line 75

def word_wrap(text, line_width = 80)
  text.gsub(/\n/, "\n\n").gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1\n").strip
end