在 Rails 3 中处理 JS/ERB 模板中的 JSON
Posted
技术标签:
【中文标题】在 Rails 3 中处理 JS/ERB 模板中的 JSON【英文标题】:Handling JSON in JS/ERB template in Rails 3 【发布时间】:2011-04-15 00:30:39 【问题描述】:使用 JSON 对象和 jQuery-rails(jQuery 库加上一个特殊的 rails.js 文件)对 Rails(3) 进行典型的 AJAX 调用和从 Rails(3) 调用我没有任何问题。
不过,在一个控制器中,我想在 AJAX 调用之后在 erb 模板 (create.js.erb) 中返回一些 JSON。
我已经尝试了控制器(@object.to_json、'["content":"hello world"]' 等)和模板本身(JSON.parse()、单引号,双引号等),但对象继续呈现如下:
'["groups":,"created_at":"2010-09-21T03:49:34Z" ...
结果,我的 jQuery 代码无法解析它,我得到了错误。
我需要如何在控制器中准备我的对象,我需要在视图中使用什么 erb 语法才能将其呈现为有效的 JSON 对象?
非常感谢!
【问题讨论】:
【参考方案1】:我不确定这是不是这个原因,但您也可以尝试使用html_safe
方法。 ERB 可能正在转义您的 JSON,因为它认为它不是 html 安全的。尝试使用字符串时调用该方法:
@object.to_json.html_safe
【讨论】:
注意:如果您将结果嵌入到脚本标签中,则在不转义的情况下调用 html_safe 可能会导致 XSS 漏洞。 查看railscast,了解如何安全使用html_safe
注意,只有在用户提供的数据(例如通过表单提交的数据)上调用 html_safe 时,在此调用 html_safe 才是危险的。如果您在后端提供的下拉列表中执行此操作,那么您就可以了。【参考方案2】:
单独使用html_escape
或raw
会留下vulnerable to XSS。
相反,定义json_escape
(又名j
)助手的合理版本:
module ActionView::Base
def json_escape(s)
result = s.to_s.gsub('/', '\/')
s.html_safe? ? result.html_safe : result
end
alias j json_escape
end
像这样使用它:
<script>
var Accounts = new Backbone.Collection;
Accounts.reset(<%=j @accounts.to_json.html_safe %>);
var Projects = new Backbone.Collection;
Projects.reset(<%=j @projects.to_json(:collaborators => true).html_safe %>);
</script>
更多详情请参阅this post。
请注意,ERB::Util 中的 j
别名为 json_escape
和 ActionView::Helpers::javascriptHelper 中的 j
别名为 escape_javascript
之间有一个 naming conflict。我希望 JavaScriptHelper 别名将重命名为 js
。
【讨论】:
这个答案应该是被接受的——互联网上有多少帖子建议使用 html_safe 而不转义,这真是令人震惊。 我认为应该是class ActionView::Base
,而不是module
。此外,是否有任何理由不默认设置为 html_safe ?我想不出你想要 json_escape 然后 html_escape 的任何情况。
快速提问:module ActionView::Base ... end
定义应该放在 Rails 项目的什么位置?是否有标准路径或文件?
Rails 4:只需要 to_json.html_safe
:'<script>'.to_json
=> "\"\\u003cscript\\u003e\""
你的意思是result.html_safe? ? result.html_safe : result
?【参考方案3】:
要返回json
,您必须在控制器中编写渲染,如下所示:
render :json => @object
.to_json
会自动被调用。
如果您想包含一些关系,您可以执行以下操作:
render :json => @post.to_json(:include => [:comments, :authors])
我不确定使用 erb 来渲染你的 json 是否可行。
【讨论】:
【参考方案4】:您可以在控制器中调用 render,但如果您可能需要渲染多个部分以供处理程序随后插入 dom,这将是一个问题。我需要将多个 html 片段设置为一个哈希,并且我已经能够返回 erb,它基本上使用 hash.to_json.html_safe,正如 neutrino 上面所建议的那样,并允许我在此过程中渲染多个部分。
【讨论】:
【参考方案5】:只需要to_json.html_safe
:
> `'<script>'.to_json`
=> "\"\\u003cscript\\u003e\""
使to_json
响应html_safe?
并自动返回true
的补丁:
# just use .to_json instead of .to_json.html_safe
ActiveSupport::JSON.class_eval do
class << self
def encode_with_html_safe *args
self.encode_without_html_safe(*args).html_safe
end
alias_method_chain :encode, :html_safe
end
end
【讨论】:
以上是关于在 Rails 3 中处理 JS/ERB 模板中的 JSON的主要内容,如果未能解决你的问题,请参考以下文章
Rails update.js.erb 不执行 javascript
Bootstrap 4 和 Rails 6:$(...).modal 不是“.js.erb”文件中的函数(但适用于其他 .js 文件?)[关闭]