Почему Rails sanitize() работает в rspec иначе, чем в модели?

В моем 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>&lt;img src=\"nonexistent.png\" onerror=\"alert('This alert should not be shown');\"/&gt;</span><p>Build something</p> "

Но в rspec вызов того же метода для той же строки приводит к следующему результату:

"<span></span><p>Build something</p>"

Он больше не кодирует тег изображения; он просто полностью удаляет тег. В чем причина такого поведения в спецификации модели и в модели?

Покажите код, о котором вы говорите, который вызывает этот метод String#sanitize, как в вашем собственном коде, так и в rspec (или укажите, имели ли вы в виду, что тот же самый код приложения при вызове из rspec приводит к удалению всего элемента).

smathy 01.06.2023 18:37

Очевидно, это тот же код: str.sanitize. Но причина этого в конечном счете заключалась в том, что редактор форматированного текста переднего плана реализовывал кодировку html перед отправкой в ​​​​API.

Ando 03.06.2023 21:17
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
52
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Трудно узнать. Легко узнать. В основном: не делай этого.

Трудно знать: Что-то еще стирает ваш метод дезинфекции или вы стираете чей-то еще?

Легко узнать: Напишите тест. Установите точку останова перед вызовом sanitize. Шагните в него и продолжайте шагать. Вы, вероятно, увидите, что происходит довольно быстро.

Не делай этого:

  1. Другие вещи либо добавляют этот метод, либо вы можете вызывать sanitize из чего-то другого. Я не уверен, какое правильное решение для вас, но, вероятно, контроллер или вспомогательный метод sanitize(string, options) лучше, чем делать то, что вы сделали. В конце концов, это то, что вы звоните.
  2. Если вам нужно добавить метод, не открывайте класс и не затирайте его, как вы сделали:
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

smathy 01.06.2023 18:36

Остальное остается в силе: не делайте этого. Отладьте его, если вам действительно нужно это сделать.

kwerle 01.06.2023 19:46

Спасибо @kwerle. Я прокомментировал причину выше, но я ценю ваш ответ, поскольку в конечном итоге он привел меня к лучшей реализации: модуль с before_save, который получает аргументы attr от модели.

Ando 03.06.2023 21:25

@Андо Это здорово! Но как говорится: "Фото или не случилось". Ответьте на свой вопрос здесь с правильным решением.

kwerle 05.06.2023 19:25

Вот решение, которое я нашел, следуя рекомендациям @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

Другие вопросы по теме