为什么在直接调用时 ActionView 的 "select_tag" 转义其 "options" 参数中的 HTML?
Why does ActionView's "select_tag" escape the HTML in its "options" argument when called directly?
所以我一直在浏览 ActionView 的非常糟糕的文档,特别是一个名为 select_tag
的方法,它只在从视图文件调用时存在。据说,它是这样称呼的:
select_tag name, option_tags, options
documentation 对 name
只字未提,对 options
也很少提及,仅通过将其视为不透明的示例来描述 option_tags
必须从其他函数获取的值。
一如既往,了解 Rails 的唯一方法是对其进行逆向工程。
所以我直接从 Rails 控制台尝试 运行 它,这很棘手,因为 Ruby 不允许您调用模块中定义的方法,除非您创建 class 和第一个对象:
class H
include ActionView::Helpers::FormOptionsHelper
include ActionView::Helpers::FormTagHelper
end
H.new.options_for_select ["foo","bar"]
上面options_for_select
的用法来自别人写的实际代码。 return 值是一个字符串:
"<option value=\"foo\">foo</option>\n<option value=\"bar\">bar</option>"
显然,您应该从 option_for_select
传递 return 值(或者许多其他相关函数之一,这些函数引入了我不想谈论的并发症,例如生成HTML 来自 ActiveRecord 对象的标签)作为 select_tag
的 option_tag
参数。除非您将该字符串复制到剪贴板并将其直接粘贴到函数调用中,否则它不会执行您期望的操作:
H.new.select_tag :my_name, "<option value=\"foo\">foo</option>\n<option value=\"bar\">bar</option>"
Return 值:
"<select name=\"my_name\" id=\"my_name\"><option value="foo">foo</option>\n<option value="bar">bar</option></select>"
至少这揭示了 name
参数的用途。
更奇怪的是,如果您将 return 值 直接 传递给 select_tag
而不让它在控制台上打印,则文本不会被转义:
H.new.select_tag :name, H.new.options_for_select(["foo","bar"])
Return 值:
"<select name=\"name\" id=\"name\"><option value=\"foo\">foo</option>\n<option value=\"bar\">bar</option></select>"
这是怎么回事?
在写这个问题的过程中,我偶然发现了它的答案:Ruby 一直在骗我(就像它一直那样)。
当您评价时:
H.new.options_for_select ["foo","bar"]
Ruby 告诉您结果是一个字符串。但这只是因为 Pry 和 Irb 都在所有事情上默默地调用 .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 将所有字符串视为可疑字符串,但可以将某些字符串标记为 "safe",方法是将它们包装在 ActiveSupport::SafeBuffer
.
中
所以我一直在浏览 ActionView 的非常糟糕的文档,特别是一个名为 select_tag
的方法,它只在从视图文件调用时存在。据说,它是这样称呼的:
select_tag name, option_tags, options
documentation 对 name
只字未提,对 options
也很少提及,仅通过将其视为不透明的示例来描述 option_tags
必须从其他函数获取的值。
一如既往,了解 Rails 的唯一方法是对其进行逆向工程。
所以我直接从 Rails 控制台尝试 运行 它,这很棘手,因为 Ruby 不允许您调用模块中定义的方法,除非您创建 class 和第一个对象:
class H
include ActionView::Helpers::FormOptionsHelper
include ActionView::Helpers::FormTagHelper
end
H.new.options_for_select ["foo","bar"]
上面options_for_select
的用法来自别人写的实际代码。 return 值是一个字符串:
"<option value=\"foo\">foo</option>\n<option value=\"bar\">bar</option>"
显然,您应该从 option_for_select
传递 return 值(或者许多其他相关函数之一,这些函数引入了我不想谈论的并发症,例如生成HTML 来自 ActiveRecord 对象的标签)作为 select_tag
的 option_tag
参数。除非您将该字符串复制到剪贴板并将其直接粘贴到函数调用中,否则它不会执行您期望的操作:
H.new.select_tag :my_name, "<option value=\"foo\">foo</option>\n<option value=\"bar\">bar</option>"
Return 值:
"<select name=\"my_name\" id=\"my_name\"><option value="foo">foo</option>\n<option value="bar">bar</option></select>"
至少这揭示了 name
参数的用途。
更奇怪的是,如果您将 return 值 直接 传递给 select_tag
而不让它在控制台上打印,则文本不会被转义:
H.new.select_tag :name, H.new.options_for_select(["foo","bar"])
Return 值:
"<select name=\"name\" id=\"name\"><option value=\"foo\">foo</option>\n<option value=\"bar\">bar</option></select>"
这是怎么回事?
在写这个问题的过程中,我偶然发现了它的答案:Ruby 一直在骗我(就像它一直那样)。
当您评价时:
H.new.options_for_select ["foo","bar"]
Ruby 告诉您结果是一个字符串。但这只是因为 Pry 和 Irb 都在所有事情上默默地调用 .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 将所有字符串视为可疑字符串,但可以将某些字符串标记为 "safe",方法是将它们包装在 ActiveSupport::SafeBuffer
.