Я пишу веб-приложение на Ruby on Rails 3. Rails 3 автоматически экранирует любые потенциально плохие строки, что, как правило, хорошо, но означает, что если вы собираете HTML самостоятельно, вы должны вызвать html_safe
для него.
У меня есть модель Card, в которой есть несколько текстовых полей, содержимое которых не является доверенным (может содержать злой HTML или скрипт). У меня есть функция, которая выполняет несколько преобразований в одном из этих текстовых полей, используя другие знания о конкретной карте, чтобы произвести вывод HTML. Я хочу встроить HTML, созданный этой функцией, в несколько мест в нескольких частях моего приложения.
Концептуально, этот помощник связан с View. Тем не менее, я не могу найти способ писать функции в моих файлах View; кажется, что они должны идти в помощники или контроллер / модель.
Поскольку эта функция очень специфична для объекта Card, следующим лучшим вариантом будет иметь функцию внутри моей модели Card.rb:
class Card < ActiveRecord::Base
[...]
def format(unsafe_text)
initial_text = h unsafe_text # aka html_escape unsafe_text
# assembles HTML output based on initial_text and fields of self
output_text.html_safe!
end
Тогда я бы хотел назвать это в разных видах, выполнив такие вещи:
Rules text: <%= format(@card.rulestext) %>
Однако и здесь есть большая проблема. В модели Card.rb карты я могу использовать функцию html_safe!
, но я не могу использовать h
или html_escape
. Кажется, что функции h
и html_escape
доступны только в представлениях ERB, но не в помощниках или контроллерах!
Есть несколько обходных путей. Я могу заставить format
не дезинфицировать свой ввод и перейти
Rules text: <%= format(h(@card.rulestext)) %>
Но это оба склонны к опасным промахам (один отсутствует h()
, и у нас есть проблемы) и очень не СУХОЙ. На данный момент я использую партиал для получения доступа к функции h()
:
(in a normal view)
Rules text: <%= render 'formattext', :text=> @card.rulestext %>
(app/views/shared/_formattext.html.erb)
<%= @card.format(html_escape(text)) %>
Но это все еще кажется опасным. Все, что мне нужно сделать, это сделать один забывчивый вызов format(sometext)
в представлении, вместо того, чтобы вызывать render 'formattext', :text=> sometext
, и у меня появляется неэкранированный текст.
Есть ли лучший способ сделать это? Есть ли способ написания вспомогательных функций для представления в представлении, а не в модели или контроллере?