Action View 文本助手¶ ↑
TextHelper 模块提供了一组用于过滤、格式化和转换字符串的方法,可以减少视图中的 Ruby 内联代码量。这些助手方法扩展了 Action View,使其可以在模板文件中调用。
转义¶ ↑
大多数生成 HTML 输出的文本助手默认会转义给定的输入,但不会对其进行 HTML 实体编码。这意味着 HTML 标签将显示在页面上,但所有恶意代码都会被移除。让我们通过 simple_format 方法看一些例子。
simple_format('<a href="http://example.com/">Example</a>') # => "<p><a href=\"http://example.com/\">Example</a></p>" simple_format('<a href="javascript:alert(\'no!\')">Example</a>') # => "<p><a>Example</a></p>"
如果您想对所有内容进行 HTML 实体编码,则应在调用文本助手之前调用 h 方法。
simple_format h('<a href="http://example.com/">Example</a>') # => "<p><a href=\"http://example.com/\">Example</a></p>"
- C
- E
- H
- P
- R
- S
- T
- W
- ActionView::Helpers::SanitizeHelper
- ActionView::Helpers::TagHelper
- ActionView::Helpers::OutputSafetyHelper
实例公共方法
concat(string) 链接
在视图中输出文本的首选方法是使用 <%= "text" %> eRuby 语法。标准的 puts 和 print 方法在 eRuby 代码块中无法按预期工作。如果您绝对必须在非输出代码块(即 <% %>)中输出文本,可以使用 concat 方法。
<% concat "hello" %> is equivalent to <%= "hello" %>
<%
   unless signed_in?
     concat link_to("Sign In", action: :sign_in)
   end
%>
is equivalent to
<% unless signed_in? %>
  <%= link_to "Sign In", action: :sign_in %>
<% end %>
            来源: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/text_helper.rb, line 63 def concat(string) output_buffer << string end
current_cycle(name = "default") 链接
返回当前循环字符串,在循环启动后。对于复杂的表格高亮或需要在多个地方使用当前循环字符串的任何其他设计需求非常有用。
<%# Alternate background colors %>
<% @items = [1,2,3,4] %>
<% @items.each do |item| %>
  <div style="background-color:<%= cycle("red","white","blue") %>">
    <span style="background-color:<%= current_cycle %>"><%= item %></span>
  </div>
<% end %>
            来源: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/text_helper.rb, line 461 def current_cycle(name = "default") cycle = get_cycle(name) cycle.current_value if cycle end
cycle(first_value, *values) 链接
创建一个 Cycle 对象,其 to_s 方法在每次调用时都会循环遍历数组中的元素。例如,这可用于交替表格行的类。您可以使用命名循环来允许在循环中嵌套。将带有 :name 键的 Hash 作为最后一个参数传递将创建一个命名循环。没有 :name 键的循环的默认名称是 "default"。您可以通过调用 reset_cycle 并传递循环的名称来手动重置循环。可以使用 current_cycle 方法随时获取当前循环字符串。
 <%# Alternate CSS classes for even and odd numbers... %>
 <% @items = [1,2,3,4] %>
 <table>
 <% @items.each do |item| %>
   <tr class="<%= cycle("odd", "even") -%>">
     <td><%= item %></td>
   </tr>
 <% end %>
 </table>
 <%# Cycle CSS classes for rows, and text colors for values within each row %>
 <% @items = [
   { first: "Robert", middle: "Daniel", last: "James" },
   { first: "Emily", middle: "Shannon", maiden: "Pike", last: "Hicks" },
   { first: "June", middle: "Dae", last: "Jones" },
 ] %>
 <% @items.each do |item| %>
   <tr class="<%= cycle("odd", "even", name: "row_class") -%>">
     <td>
       <% item.values.each do |value| %>
         <%# Create a named cycle "colors" %>
         <span style="color:<%= cycle("red", "green", "blue", name: "colors") -%>">
           <%= value %>
         </span>
       <% end %>
       <% reset_cycle("colors") %>
     </td>
  </tr>
<% end %>
            来源: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/text_helper.rb, line 437 def cycle(first_value, *values) options = values.extract_options! name = options.fetch(:name, "default") values.unshift(*first_value) cycle = get_cycle(name) unless cycle && cycle.values == values cycle = set_cycle(name, Cycle.new(*values)) end cycle.to_s end
excerpt(text, phrase, options = {}) 链接
从 text 中提取 phrase 的第一个出现及其周围的文本。如果结果的开头/结尾与 text 的开头/结尾不一致,则会在结果前面/后面加上省略标记。无论如何,结果都会被清除。如果找不到 phrase,则返回 nil。
选项¶ ↑
- :radius
- 
要包含在结果中的 phrase周围的字符数(或标记 - 请参阅:separator选项)。默认为 100。
- :omission
- 
当摘录的开头/结尾与 text的开头/结尾不一致时,要添加到开头/结尾的标记。默认为"..."。
- :separator
- 
用于计算 :radius的标记之间的分隔符。默认为"",它将每个字符视为一个标记。
示例¶ ↑
excerpt('This is an example', 'an', radius: 5) # => "...s is an exam..." excerpt('This is an example', 'is', radius: 5) # => "This is a..." excerpt('This is an example', 'is') # => "This is an example" excerpt('This next thing is an example', 'ex', radius: 2) # => "...next..." excerpt('This is also an example', 'an', radius: 8, omission: '<chop> ') # => "<chop> is also an example" excerpt('This is a very beautiful morning', 'very', separator: ' ', radius: 1) # => "...a very beautiful..."
来源: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/text_helper.rb, line 235 def excerpt(text, phrase, options = {}) return unless text && phrase separator = options.fetch(:separator, nil) || "" case phrase when Regexp regex = phrase else regex = /#{Regexp.escape(phrase)}/i end return unless matches = text.match(regex) phrase = matches[0] unless separator.empty? text.split(separator).each do |value| if value.match?(regex) phrase = value break end end end first_part, second_part = text.split(phrase, 2) prefix, first_part = cut_excerpt_part(:first, first_part, separator, options) postfix, second_part = cut_excerpt_part(:second, second_part, separator, options) affix = [ first_part, !first_part.empty? ? separator : "", phrase, !second_part.empty? ? separator : "", second_part ].join.strip [prefix, affix, postfix].join end
highlight(text, phrases, options = {}, &block) 链接
通过使用高亮字符串格式化来突出显示 text 中 phrases 的出现。phrases 可以是一个或多个字符串或正则表达式。结果将被标记为 HTML 安全。默认情况下,在进行高亮显示之前会对 text 进行转义,以防止潜在的 XSS 攻击。
如果指定了块,它将代替高亮字符串。每次出现短语时都会传递给块,其返回值将插入到最终结果中。
选项¶ ↑
- :highlighter
- 
高亮字符串。使用 \1作为短语的占位符,类似于 +String#sub+。默认为"<mark>\1</mark>"。如果指定了块,则忽略此选项。
- :sanitize
- 
是否在高亮显示之前转义 text。默认为 true。
示例¶ ↑
highlight('You searched for: rails', 'rails') # => "You searched for: <mark>rails</mark>" highlight('You searched for: rails', /for|rails/) # => "You searched <mark>for</mark>: <mark>rails</mark>" highlight('You searched for: ruby, rails, dhh', 'actionpack') # => "You searched for: ruby, rails, dhh" highlight('You searched for: rails', ['for', 'rails'], highlighter: '<em>\1</em>') # => "You searched <em>for</em>: <em>rails</em>" highlight('You searched for: rails', 'rails', highlighter: '<a href="search?q=\1">\1</a>') # => "You searched for: <a href=\"search?q=rails\">rails</a>" highlight('You searched for: rails', 'rails') { |match| link_to(search_path(q: match)) } # => "You searched for: <a href=\"search?q=rails\">rails</a>" highlight('<a href="javascript:alert(\'no!\')">ruby</a> on rails', 'rails', sanitize: false) # => "<a href=\"javascript:alert('no!')\">ruby</a> on <mark>rails</mark>"
来源: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/text_helper.rb, line 174 def highlight(text, phrases, options = {}, &block) text = sanitize(text) if options.fetch(:sanitize, true) if text.blank? || phrases.blank? text || "" else patterns = Array(phrases).map { |phrase| Regexp === phrase ? phrase : Regexp.escape(phrase) } pattern = /(#{patterns.join("|")})/i highlighter = options.fetch(:highlighter, '<mark>\1</mark>') unless block text.scan(/<[^>]*|[^<]+/).each do |segment| if !segment.start_with?("<") if block segment.gsub!(pattern, &block) else segment.gsub!(pattern, highlighter) end end end.join end.html_safe end
pluralize(count, singular, plural_arg = nil, plural: plural_arg, locale: I18n.locale) 链接
尝试将 singular 单词进行复数化,除非 count 为 1。如果提供了 plural,则当 count > 1 时使用它,否则它将使用 Inflector 来确定给定区域设置的复数形式,默认值为 I18n.locale。
该单词将使用为区域设置定义的规则进行复数化(您必须为英语以外的语言定义自己的变位规则)。请参阅 ActiveSupport::Inflector.pluralize。
pluralize(1, 'person') # => "1 person" pluralize(2, 'person') # => "2 people" pluralize(3, 'person', plural: 'users') # => "3 users" pluralize(0, 'person') # => "0 people" pluralize(2, 'Person', locale: :de) # => "2 Personen"
来源: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/text_helper.rb, line 297 def pluralize(count, singular, plural_arg = nil, plural: plural_arg, locale: I18n.locale) word = if count == 1 || count.to_s.match?(/^1(\.0+)?$/) singular else plural || singular.pluralize(locale) end "#{count || 0} #{word}" end
reset_cycle(name = "default") 链接
重置一个循环,以便下次调用时从第一个元素开始。传入 name 来重置一个命名循环。
<%# Alternate CSS classes for even and odd numbers... %>
<% @items = [[1,2,3,4], [5,6,3], [3,4,5,6,7,4]] %>
<table>
<% @items.each do |item| %>
  <tr class="<%= cycle("even", "odd") -%>">
      <% item.each do |value| %>
        <span style="color:<%= cycle("#333", "#666", "#999", name: "colors") -%>">
          <%= value %>
        </span>
      <% end %>
      <% reset_cycle("colors") %>
  </tr>
<% end %>
</table>
            来源: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/text_helper.rb, line 484 def reset_cycle(name = "default") cycle = get_cycle(name) cycle.reset if cycle end
safe_concat(string) 链接
来源: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/text_helper.rb, line 67 def safe_concat(string) output_buffer.respond_to?(:safe_concat) ? output_buffer.safe_concat(string) : concat(string) end
simple_format(text, html_options = {}, options = {}) 链接
使用简单的格式规则将 text 转换为 HTML。两个或多个连续的换行符(\n\n 或 \r\n\r\n)被视为一个段落并包装在 <p> 标签中。一个换行符(\n 或 \r\n)被视为一个换行符,并附加一个 <br /> 标签。此方法不会从 text 中删除换行符。
您可以将任何 HTML 属性传递给 html_options。这些属性将添加到所有创建的段落中。
选项¶ ↑
- 
:sanitize- 如果为false,则不对text进行转义。
- 
:sanitize_options- 您想附加到转义的任何额外选项。
- 
:wrapper_tag-String表示包装标签,默认为"p"。
示例¶ ↑
my_text = "Here is some basic text...\n...with a line break." simple_format(my_text) # => "<p>Here is some basic text...\n<br />...with a line break.</p>" simple_format(my_text, {}, wrapper_tag: "div") # => "<div>Here is some basic text...\n<br />...with a line break.</div>" more_text = "We want to put a paragraph...\n\n...right there." simple_format(more_text) # => "<p>We want to put a paragraph...</p>\n\n<p>...right there.</p>" simple_format("Look ma! A class!", class: 'description') # => "<p class='description'>Look ma! A class!</p>" simple_format("<blink>Unblinkable.</blink>") # => "<p>Unblinkable.</p>" simple_format("<blink>Blinkable!</blink> It's true.", {}, sanitize: false) # => "<p><blink>Blinkable!</blink> It's true.</p>" simple_format("<a target=\"_blank\" href=\"http://example.com\">Continue</a>", {}, { sanitize_options: { attributes: %w[target href] } }) # => "<p><a target=\"_blank\" href=\"http://example.com\">Continue</a></p>"
来源: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/text_helper.rb, line 383 def simple_format(text, html_options = {}, options = {}) wrapper_tag = options[:wrapper_tag] || "p" text = sanitize(text, options.fetch(:sanitize_options, {})) if options.fetch(:sanitize, true) paragraphs = split_paragraphs(text) if paragraphs.empty? content_tag(wrapper_tag, nil, html_options) else paragraphs.map! { |paragraph| content_tag(wrapper_tag, raw(paragraph), html_options) }.join("\n\n").html_safe end end
truncate(text, options = {}, &block) 链接
如果 text 长度超过指定的 :length,则将其截断。如果 text 被截断,则会在结果后面附加一个省略标记,总长度不超过 :length。
您还可以传递一个块来渲染并显示省略标记后的额外内容,当 text 被截断时。但是,此内容可能会导致总长度超过 :length 个字符。
结果将被 HTML 实体编码,除非指定了 escape: false。无论如何,结果都将被标记为 HTML 安全。如果 text 可能包含 HTML 标签或实体,则应格外小心,因为截断可能产生无效的 HTML,例如未配对或不完整的标签。
选项¶ ↑
- :length
- 
应返回的最大字符数,不包括块中的任何额外内容。默认为 30。 
- :omission
- 
截断后要附加的字符串。默认为 "..."。
- :separator
- 
用于查找截断点的字符串或正则表达式。默认情况下,截断可以在 text中的任何字符处发生。
- :escape
- 
是否对结果进行 HTML 实体编码。默认为 true。 
示例¶ ↑
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)" truncate("<p>Once upon a time in a world far far away</p>") # => "<p>Once upon a time in a wo..." truncate("<p>Once upon a time in a world far far away</p>", escape: false) # => "<p>Once upon a time in a wo..." truncate("Once upon a time in a world far far away") { link_to "Continue", "#" } # => "Once upon a time in a world...<a href=\"#\">Continue</a>"
来源: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/text_helper.rb, line 122 def truncate(text, options = {}, &block) if text length = options.fetch(:length, 30) content = text.truncate(length, options) content = options[:escape] == false ? content.html_safe : ERB::Util.html_escape(content) content << capture(&block) if block_given? && text.length > length content end end
word_wrap(text, line_width: 80, break_sequence: "\n") 链接
将 text 包装成不超过 line_width 宽度的行。此方法在不超过 line_width(默认为 80)的第一个空格处断开。
word_wrap('Once upon a time') # => "Once upon a time" word_wrap('Once upon a time, in a kingdom called Far Far Away, a king fell ill, and finding a successor to the throne turned out to be more trouble than anyone could have imagined...') # => "Once upon a time, in a kingdom called Far Far Away, a king fell ill, and finding\na successor to the throne turned out to be more trouble than anyone could have\nimagined..." word_wrap('Once upon a time', line_width: 8) # => "Once\nupon a\ntime" word_wrap('Once upon a time', line_width: 1) # => "Once\nupon\na\ntime"
您还可以指定自定义的 break_sequence(默认为“\n”)
word_wrap('Once upon a time', line_width: 1, break_sequence: "\r\n") # => "Once\r\nupon\r\na\r\ntime"
来源: 显示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/text_helper.rb, line 327 def word_wrap(text, line_width: 80, break_sequence: "\n") return +"" if text.empty? # Match up to `line_width` characters, followed by one of # (1) non-newline whitespace plus an optional newline # (2) the end of the string, ignoring any trailing newlines # (3) a newline # # -OR- # # Match an empty line pattern = /(.{1,#{line_width}})(?:[^\S\n]+\n?|\n*\Z|\n)|\n/ text.gsub(pattern, "\\1#{break_sequence}").chomp!(break_sequence) end