В моем config/initializers
я добавил следующее в класс String
:
class String
def sanitize(options = { tags: %w(div p span strong b em i br ol ul li) })
ActionController::Base.helpers.sanitize(self, options)
end
end
На моем локальном сайте разработки это преобразует все запрещенные теги в закодированный html, поэтому
"<span><img src=\"nonexistent.png\" onerror=\"alert('This alert should not be shown');\"></span><p>Build something</p>"
становится
"<span><img src=\"nonexistent.png\" onerror=\"alert('This alert should not be shown');\"/></span><p>Build something</p> "
Но в rspec вызов того же метода для той же строки приводит к следующему результату:
"<span></span><p>Build something</p>"
Он больше не кодирует тег изображения; он просто полностью удаляет тег. В чем причина такого поведения в спецификации модели и в модели?
Очевидно, это тот же код: str.sanitize
. Но причина этого в конечном счете заключалась в том, что редактор форматированного текста переднего плана реализовывал кодировку html перед отправкой в API.
Трудно узнать. Легко узнать. В основном: не делай этого.
Трудно знать: Что-то еще стирает ваш метод дезинфекции или вы стираете чей-то еще?
Легко узнать: Напишите тест. Установите точку останова перед вызовом sanitize. Шагните в него и продолжайте шагать. Вы, вероятно, увидите, что происходит довольно быстро.
Не делай этого:
sanitize(string, options)
лучше, чем делать то, что вы сделали. В конце концов, это то, что вы звоните.module StringSanitizer
def sanitize(...)
super # if appropriate - see if it already exists in the class or if something else has already added it
ActionController::Base.helpers.sanitize(self, options)
end
end
String.prepend(StringSanitizer)
Для String нет метода очистки: String.instance_methods.include? :sanitize # => false
Остальное остается в силе: не делайте этого. Отладьте его, если вам действительно нужно это сделать.
Спасибо @kwerle. Я прокомментировал причину выше, но я ценю ваш ответ, поскольку в конечном итоге он привел меня к лучшей реализации: модуль с before_save
, который получает аргументы attr от модели.
@Андо Это здорово! Но как говорится: "Фото или не случилось". Ответьте на свой вопрос здесь с правильным решением.
Вот решение, которое я нашел, следуя рекомендациям @kwerle:
module Sanitizable
extend ActiveSupport::Concern
class_methods do
def sanitizable(*attributes)
before_save do |record|
attributes.each do |attribute|
record[attribute] = ActionController::Base.helpers.sanitize(record[attribute], tags: %w(p span strong b em i br ol ul li))
end
end
end
end
end
и это можно использовать в модели с:
include Sanitizable
sanitizable :subtitle, :description
Покажите код, о котором вы говорите, который вызывает этот метод
String#sanitize
, как в вашем собственном коде, так и в rspec (или укажите, имели ли вы в виду, что тот же самый код приложения при вызове из rspec приводит к удалению всего элемента).