Почему 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>"

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

🤔 А знаете ли вы, что...
Ruby on Rails также известен как Rails или RoR.


52
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)

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