Почему ActionView "select_tag" экранирует HTML в аргументе "options" при прямом вызове?

Итак, я просматривал очень скудную документацию, которая существует для ActionView, в частности, метод под названием select_tag это просто существует, когда вызывается из файлов просмотра. Предположительно, это называется так:

select_tag name, option_tags, options

Документация ничего не говорит о nameочень мало о optionsи описывает option_tags только через примеры, которые рассматривают его как непрозрачное значение, которое должно быть получено из других функций.

Как всегда, единственный способ узнать что-либо о Rails - это перепроектировать его.

Поэтому я попытался запустить его непосредственно из консоли Rails, что сложно, поскольку Ruby не позволяет вам вызывать методы, определенные в модулях, если вы сначала не создадите класс и объект:

class H
  include ActionView::Helpers::FormOptionsHelper
  include ActionView::Helpers::FormTagHelper
end

H.new.options_for_select ["foo","bar"]

Вышеуказанное использование options_for_select исходит из реального кода, который кто-то написал. Возвращаемое значение представляет собой строку:

"<option value=\"foo\">foo</option>\n<option value=\"bar\">bar</option>"

Очевидно, вы должны передать возвращаемое значение из option_for_select (или одна из многих других связанных функций, которые создают сложности, о которых я не хочу говорить, например, генерирование тегов HTML из объектов ActiveRecord) в качестве option_tag параметр select_tag, За исключением случаев, когда вы копируете эту строку в буфер обмена и вставляете ее непосредственно в вызов функции, она не делает то, что вы ожидаете:

H.new.select_tag :my_name, "<option value=\"foo\">foo</option>\n<option value=\"bar\">bar</option>"

Возвращаемое значение:

"<select name=\"my_name\" id=\"my_name\">&lt;option value=&quot;foo&quot;&gt;foo&lt;/option&gt;\n&lt;option value=&quot;bar&quot;&gt;bar&lt;/option&gt;</select>"

По крайней мере, это показывает, что name параметр для.

Даже страннее, текст не экранируется, если вы передаете возвращаемое значение непосредственно select_tag не позволяя печатать на консоли:

H.new.select_tag :name, H.new.options_for_select(["foo","bar"])

Возвращаемое значение:

"<select name=\"name\" id=\"name\"><option value=\"foo\">foo</option>\n<option value=\"bar\">bar</option></select>"

WTF здесь происходит?

1 ответ

Решение

В процессе написания этого вопроса я наткнулся на его ответ: Руби лгала мне (как всегда).

Когда вы оцениваете:

H.new.options_for_select ["foo","bar"]

Руби говорит вам, что результатом была строка. Но это только потому, что Прай и Ирб молча .to_s на все, и вещь, которая возвращается из options_for_select имеет to_s, Правда:

(H.new.options_for_select ["foo","bar"]).class
=> ActiveSupport::SafeBuffer
ActiveSupport::SafeBuffer.new("<foo>")
=> "<foo>"

Так что, кто бы ни писал эти методы, предполагал, что вы хотите включить необработанные, предоставленные пользователем строки в ваш <select> теги, и эти строки могут содержать попытки внедрения HTML/JavaScript, поэтому их необходимо экранировать.

ActiveView рассматривает все строки как подозрительные, но можно пометить определенные строки как "безопасные", заключив их в ActiveSupport::SafeBuffer,

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