Spec-Zone.ru › Ruby on Rails 7.2

модуль ActionView::Helpers::TextHelper

Включенные модули:
ActionView::Helpers::SanitizeHelper, ActionView::Helpers::TagHelper, ActionView::Helpers::OutputSafetyHelper

Справочник по обработке текста Action View

Модуль TextHelper предоставляет набор методов для фильтрации, форматирования и преобразования строк, что позволяет уменьшить количество встроенного кода Ruby в ваших представлениях. Эти вспомогательные методы расширяют Action View, делая их вызываемыми внутри ваших шаблонов.

Саннитизация

Большинство вспомогательных методов для генерации 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>"

Если вы хотите экранировать все содержимое, необходимо вызвать метод h перед вызовом вспомогательного метода для обработки текста.

simple_format h('<a href="http://example.com/">Example</a>')
# => "<p>&lt;a href=\"http://example.com/\"&gt;Example&lt;/a&gt;</p>"

Методы Публичного Экземпляра

concat(строка) Показать исходный код
# File actionview/lib/action_view/helpers/text_helper.rb, line 63
def concat(string)
  output_buffer << string
end

Предпочтительный метод вывода текста в ваших представлениях — использование синтаксиса eRuby. Обычные методы и методы не работают как ожидается в блоке кода 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 %>
current_cycle(имя = "по умолчанию") Показать исходный код
# File actionview/lib/action_view/helpers/text_helper.rb, line 454
def current_cycle(name = "default")
  cycle = get_cycle(name)
  cycle.current_value if cycle
end

Возвращает текущую строку цикла после начала цикла. Полезно для сложного выделения таблиц или любых других потребностей дизайна, которые требуют текущей строки цикла более чем в одном месте.

<%# 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 %>
cycle(первое_значение, *значения) Показать исходный код
# File actionview/lib/action_view/helpers/text_helper.rb, line 430
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

Создаёт объект Cycle, чья метод to_s циклически проходит через элементы массива каждый раз, когда он вызывается. Это можно использовать, например, для чередования классов строк таблицы. Вы можете использовать именованные циклы для вложенности в циклах. Передача Hash в качестве последнего параметра с ключом :name создаст именованный цикл. Значение по умолчанию для цикла без ключа :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 %>
excerpt(текст, фраза, options = {}) Показать исходный код
# 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, separator, phrase, separator, second_part].join.strip
  [prefix, affix, postfix].join
end

Извлекает первое вхождение phrase и окружающего текста из text. Если начало/конец результата не совпадает с началом/концом text, добавляется маркер пропуска. Результат всегда очищается. Возвращает nil если phrase не найдено.

Параметры

:radius

Количество символов (или токенов — см. параметр :separator) вокруг phrase для включения в результат. По умолчанию 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..."
highlight(текст, фразы, options = {}, &block) Показать исходный код
# 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

Выделяет вхождения phrases в text, форматируя их с помощью строки выделения. 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, 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>"
pluralize(счёт, единственное, множественное = nil, plural: plural_arg, locale: I18n.locale) Показать исходный код
# File actionview/lib/action_view/helpers/text_helper.rb, line 290
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

Попытка сделать слово singular множественным, если count не равно 1. Если plural предоставлено, оно будет использоваться, когда счёт > 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"
reset_cycle(имя = "по умолчанию") Показать исходный код
# File actionview/lib/action_view/helpers/text_helper.rb, line 477
def reset_cycle(name = "default")
  cycle = get_cycle(name)
  cycle.reset if cycle
end

Сбрасывает цикл, чтобы он начинался с первого элемента в следующий раз, когда он вызывается. Передайте 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>
safe_concat(строка) Показать исходный код
# 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(текст, html_options = {}, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/text_helper.rb, line 376
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

Возвращает 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>"
truncate(текст, options = {}, &block) Показать исходный код
# 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

Усекает text если он длиннее указанной :length. Если text усечён, к результату будет добавлен маркер пропуска, общая длина которого не будет превышать :length.

Также можно передать блок для рендеринга и добавления дополнительного содержимого после маркера пропуска, когда text усекается. Однако это содержимое может привести к превышению общей длины :length символов.

Результат будет экранирован, если не указан escape: false . В любом случае, результат будет помечен как безопасный для HTML. Следует быть осторожным, если text может содержать теги HTML или сущности, поскольку усечение может привести к созданию некорректного HTML, такого как несбалансированные или неполные теги.

Параметры

:length

Максимальное количество символов, которые должны быть возвращены, не включая дополнительное содержимое из блока. По умолчанию 30.

:omission

Строка, добавляемая после усечения. По умолчанию "...".

:separator

Строка или регулярное выражение, используемое для поиска точки разрыва для усечения. По умолчанию усечение может происходить в любом символе text.

:escape

Нужно ли экранировать результат. По умолчанию 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>")
# => "&lt;p&gt;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>"
word_wrap(text, line_width: 80, break_sequence: "\n") Показать исходный код
# File actionview/lib/action_view/helpers/text_helper.rb, line 320
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

Обрезает текст 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"

© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API