Spec-Zone.ru › Ruby on Rails 7.1

модуль 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(string) Показать исходный код
# File actionview/lib/action_view/helpers/text_helper.rb, line 59
def concat(string)
  output_buffer << string
end

Предпочтительный способ вывода текста в ваших представлениях — использование синтаксиса eRuby <%= “текст” %>. Обычные методы puts и print не работают так, как ожидается, в блоке кода eRuby. Если вам абсолютно необходимо вывести текст внутри блока кода, который не отображает вывод (например, <% %>), вы можете использовать метод concat.

<%
    concat "hello"
    # is the equivalent of <%= "hello" %>

    if logged_in
      concat "Logged in!"
    else
      concat link_to('login', action: :login)
    end
    # will either display "Logged in!" or a login link
%>
current_cycle(name = "default") Показать исходный код
# File actionview/lib/action_view/helpers/text_helper.rb, line 398
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(first_value, *values) Показать исходный код
# File actionview/lib/action_view/helpers/text_helper.rb, line 374
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 = x = [{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(text, phrase, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/text_helper.rb, line 183
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

Извлекает выдержку из text, которая соответствует первой встрече phrase. Опция :radius расширяет выдержку с каждой стороны от первого вхождения phrase на количество символов, определенное в :radius (по умолчанию 100). Если радиус выдержки выходит за пределы начала или конца text, то опция :omission (по умолчанию «…»), соответственно, будет добавлена в начало/конец. Используйте опцию :separator для выбора разделителя. Полученная строка будет очищена в любом случае. Если phrase не найдена, возвращается nil.

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(text, phrases, options = {}, &block) Показать исходный код
# File actionview/lib/action_view/helpers/text_helper.rb, line 137
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, вставляя их в строку :highlighter. Подсветка может быть специализирована путем передачи :highlighter в виде одиночной строки с \1, где должна быть вставлена фраза (по умолчанию <mark>\1</mark>) или путем передачи блока, который получает каждый сопоставленный термин. По умолчанию text саннитизируется для предотвращения возможных атак XSS. Если входные данные надёжны, передача false для :sanitize выключит саннитизацию.

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(count, singular, plural_arg = nil, plural: plural_arg, locale: I18n.locale) Показать исходный код
# File actionview/lib/action_view/helpers/text_helper.rb, line 238
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 указан, он будет использован, когда 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
reset_cycle(name = "default") Показать исходный код
# File actionview/lib/action_view/helpers/text_helper.rb, line 421
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(string) Показать исходный код
# File actionview/lib/action_view/helpers/text_helper.rb, line 63
def safe_concat(string)
  output_buffer.respond_to?(:safe_concat) ? output_buffer.safe_concat(string) : concat(string)
end
simple_format(text, html_options = {}, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/text_helper.rb, line 322
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(text, options = {}, &block) Показать исходный код
# File actionview/lib/action_view/helpers/text_helper.rb, line 99
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 (по умолчанию 30). Последние символы будут заменены на :omission (по умолчанию «…»), для общей длины, не превышающей :length.

Передайте :separator для усечения text на естественном разрыве.

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

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

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 wo...<a href="#">Continue</a>"
word_wrap(text, line_width: 80, break_sequence: "\n") Показать исходный код
# File actionview/lib/action_view/helpers/text_helper.rb, line 268
def word_wrap(text, line_width: 80, break_sequence: "\n")
  # 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

You can also specify a custom +break_sequence+ ("\n" by default)

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