【问题标题】:Handling JSON in JS/ERB template in Rails 3在 Rails 3 中处理 JS/ERB 模板中的 JSON
【发布时间】: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 对象?

非常感谢!

【问题讨论】:

    标签: jquery ruby-on-rails ajax json erb


    【解决方案1】:

    我不确定这是不是这个原因,但您也可以尝试使用html_safe 方法。 ERB 可能正在转义您的 JSON,因为它认为它不是 html 安全的。尝试使用字符串时调用该方法:

    @object.to_json.html_safe
    

    【讨论】:

    • 注意:如果您将结果嵌入到脚本标签中,则在不转义的情况下调用 html_safe 可能会导致 XSS 漏洞。
    • 查看railscast,了解如何安全使用html_safe
    • 注意,只有在用户提供的数据(例如通过表单提交的数据)上调用 html_safe 时,在此调用 html_safe 才是危险的。如果您在后端提供的下拉列表中执行此操作,那么您就可以了。
    【解决方案2】:

    单独使用html_escaperaw 会留下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'&lt;script&gt;'.to_json =&gt; "\"\\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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-12-10
          • 2011-10-14
          • 2011-05-14
          • 1970-01-01
          • 1970-01-01
          • 2014-01-24
          • 1970-01-01
          • 2014-03-11
          相关资源
          最近更新 更多