модуль ActionView::Helpers::TextHelper
Модуль TextHelper предоставляет набор методов для фильтрации, форматирования и преобразования строк, что может уменьшить количество встроенного кода Ruby в ваших представлениях. Эти вспомогательные методы расширяют Action View, делая их вызываемыми в ваших файлах шаблонов.
Саннизация
Большинство вспомогательных методов для текста по умолчанию саннизируют заданное содержимое, но не экранируют его. Это означает, что теги 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><a href=\"http://example.com/\">Example</a></p>"
Открытые методы экземпляров
Предпочтительный метод вывода текста в ваших представлениях — использование синтаксиса 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
%> # File actionview/lib/action_view/helpers/text_helper.rb, line 52 def concat(string) output_buffer << string 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 %> # File actionview/lib/action_view/helpers/text_helper.rb, line 342 def current_cycle(name = "default") cycle = get_cycle(name) cycle.current_value if cycle end
Создаёт объект Cycle, метод to_s которого циклически просматривает элементы массива каждый раз при его вызове. Это можно использовать, например, для чередования классов для строк таблиц. Вы можете использовать именованные циклы для вложенности в циклах. Передача хэша в качестве последнего параметра с ключом :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 %> # File actionview/lib/action_view/helpers/text_helper.rb, line 318
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 Извлекает выдержку из 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...
# File actionview/lib/action_view/helpers/text_helper.rb, line 155
def excerpt(text, phrase, options = {})
return unless text && phrase
separator = options[:separator] || ''
phrase = Regexp.escape(phrase)
regex = /#{phrase}/i
return unless matches = text.match(regex)
phrase = matches[0]
unless separator.empty?
text.split(separator).each do |value|
if value.match(regex)
regex = phrase = value
break
end
end
end
first_part, second_part = text.split(regex, 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 Подсвечивает одно или несколько phrases повсюду в text, вставляя его в строку :highlighter. Подсветка может быть специализирована путём передачи :highlighter в виде строки в одинарных кавычках с \1 там, где должна быть вставлена фраза (по умолчанию '<mark>1</mark>').
highlight('You searched for: rails', 'rails')
# => You searched for: <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>
# File actionview/lib/action_view/helpers/text_helper.rb, line 119
def highlight(text, phrases, options = {})
text = sanitize(text) if options.fetch(:sanitize, true)
if text.blank? || phrases.blank?
text
else
highlighter = options.fetch(:highlighter, '<mark>\1</mark>')
match = Array(phrases).map { |p| Regexp.escape(p) }.join('|')
text.gsub(/(#{match})(?![^<]*?>)/i, highlighter)
end.html_safe
end Пытается сделать слово singular множественным числом, если count не равно 1. Если plural предоставлено, оно будет использоваться, когда count > 1, в противном случае оно будет использовать Inflector для определения формы множественного числа.
pluralize(1, 'person') # => 1 person pluralize(2, 'person') # => 2 people pluralize(3, 'person', 'users') # => 3 users pluralize(0, 'person') # => 0 people
# File actionview/lib/action_view/helpers/text_helper.rb, line 198
def pluralize(count, singular, plural = nil)
word = if (count == 1 || count =~ /^1(\.0+)?$/)
singular
else
plural || singular.pluralize
end
"#{count || 0} #{word}"
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> # File actionview/lib/action_view/helpers/text_helper.rb, line 365 def reset_cycle(name = "default") cycle = get_cycle(name) cycle.reset if cycle end
# File actionview/lib/action_view/helpers/text_helper.rb, line 56 def safe_concat(string) output_buffer.respond_to?(:safe_concat) ? output_buffer.safe_concat(string) : concat(string) end
Возвращает text, преобразованное в HTML с помощью простых правил форматирования. Два или более последовательных переноса строки (\n\n) считаются абзацем и заключаются в теги <p>. Один перенос строки (\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>"
# File actionview/lib/action_view/helpers/text_helper.rb, line 266
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 после заданного :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>")
# => "<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 wo...<a href="#">Continue</a>"
# File actionview/lib/action_view/helpers/text_helper.rb, line 92
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 на строки не длиннее 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
# File actionview/lib/action_view/helpers/text_helper.rb, line 223
def word_wrap(text, options = {})
line_width = options.fetch(:line_width, 80)
text.split("\n").collect! do |line|
line.length > line_width ? line.gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1\n").strip : line
end * "\n"
end
© 2004–2016 David Heinemeier Hansson
Licensed under the MIT License.