Rails 3: Где должен жить помощник, использующий h (т.е. html_escape)? - PullRequest
1 голос
/ 11 октября 2010

Я пишу веб-приложение на 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, и у меня появляется неэкранированный текст.

Есть ли лучший способ сделать это? Есть ли способ написания вспомогательных функций для представления в представлении, а не в модели или контроллере?

Ответы [ 2 ]

2 голосов
/ 12 октября 2010

Поместите логику, которая выполняет сборку вашего вида в CardHelper:

приложение / хелперы / card_helper.rb

class CardHelper
  def rules(card)
    initial_text = h card.rules_text
    # assembles HTML output based on initial_text and fields of card
    output_text.html_safe
  end
end

Из вашего примера не ясно, хотите ли вы отформатировать несколько полей с помощью метода format. Если это так, то вы можете сделать:

class CardHelper
  def format(card, attribute)
    initial_text = h card[attribute]
    # assembles HTML output based on initial_text and fields of card
    output_text.html_safe
  end
end

Вы можете использовать этот помощник, как и любой другой:

class CardsController
  helper CardHelper
end

и по вашему мнению:

<%= rules(@card) %>

или

<%= format(@card, :rules) %>
2 голосов
/ 11 октября 2010

Исключение содержимого для просмотра является обязанностью View, поэтому помощник h недоступен в контроллерах или моделях.

Тем не менее, я не понимаю, почему вы не можете просто санировать содержимое в представлении.

Также обратите внимание, что в Rails 3 вам не нужно вызывать хелпер h. По умолчанию контент очищается автоматически, если только вы не пометите его как html_safe!.

Основная причина, по которой логически неверно использовать помощник h в модели, заключается в том, что модель должна работать независимо от вида. Другими словами, модель не должна заботиться о том, будет ли содержимое встраиваться в документ HTML или файл JSON (для этого требуется иной подход к экранированию по сравнению с HTML).

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