0

因此,我一直在浏览 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或许多其他相关函数之一,这些函数引入了我不想谈论的复杂性,例如从 ActiveRecord 对象生成 HTML 标记)作为. 除非您将该字符串复制到剪贴板并将其直接粘贴到函数调用中,否则它不会执行您期望的操作:option_tagselect_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在这里进行吗?

4

1 回答 1

0

在写这个问题的过程中,我偶然发现了它的答案: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 将所有字符串都视为可疑字符串,但可以通过将某些字符串包装在ActiveSupport::SafeBuffer.

于 2017-05-24T23:05:51.930 回答