Spec-Zone.ru › Ruby on Rails 5.2

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

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

Модуль 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 54
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(имя = "по умолчанию") Показать исходный код
# File actionview/lib/action_view/helpers/text_helper.rb, line 378
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 354
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(текст, фраза, options = {}) Показать исходный код
# File actionview/lib/action_view/helpers/text_helper.rb, line 175
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(текст, фразы, options = {}) { |found| ... } Показать исходный код
# File actionview/lib/action_view/helpers/text_helper.rb, line 132
def highlight(text, phrases, options = {})
  text = sanitize(text) if options.fetch(:sanitize, true)

  if text.blank? || phrases.blank?
    text || ""
  else
    match = Array(phrases).map do |p|
      Regexp === p ? p.to_s : Regexp.escape(p)
    end.join("|")

    if block_given?
      text.gsub(/(#{match})(?![^<]*?>)/i) { |found| yield found }
    else
      highlighter = options.fetch(:highlighter, '<mark>\1</mark>')
      text.gsub(/(#{match})(?![^<]*?>)/i, highlighter)
    end
  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(количество, единственное, множественное = nil, множественное: множественное, язык: I18n.locale) Показать исходный код
# File actionview/lib/action_view/helpers/text_helper.rb, line 230
def pluralize(count, singular, plural_arg = nil, plural: plural_arg, locale: I18n.locale)
  word = if (count == 1 || count =~ /^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 401
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 58
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 302
def simple_format(text, html_options = {}, options = {})
  wrapper_tag = options.fetch(:wrapper_tag, :p)

  text = sanitize(text) 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.

  • :wrapper_tag - Строка представляющая тег обертки, по умолчанию "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>"
truncate(текст, options = {}, &block) Показать исходный код
# File actionview/lib/action_view/helpers/text_helper.rb, line 94
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(текст, ширина_строки: 80, последовательность_разрыва: "\n") Показать исходный код
# File actionview/lib/action_view/helpers/text_helper.rb, line 260
def word_wrap(text, line_width: 80, break_sequence: "\n")
  text.split("\n").collect! do |line|
    line.length > line_width ? line.gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1#{break_sequence}").strip : line
  end * 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–2018 David Heinemeier Hansson
Licensed under the MIT License.

Spec-Zone.ru

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