在ajax请求中发布长嵌套列表时,堆栈级别太深

时间:2013-12-11 22:55:18

标签: jquery ruby-on-rails post rack nested-lists

我在firebug上发布了一个看起来像这个图像的长嵌套列表:

long nested list http://i.imm.io/1m4s2.jpeg

虽然你可以在同一张图片中看到帖子成功,但日志上出现的唯一内容是以下几行:

[2013-12-11 20:50:37] ERROR SystemStackError: stack level too deep /home/fotanus/.rvm/gems/ruby-2.0.0-p247/gems/rack-1.5.2/lib/rack/utils.rb:527

似乎没有在Rails上执行任何操作。

使用以下行发送长列表:

$.ajax({ type: "POST", url: '/projects', data: JSON.stringify({ sortd_items: sorted_items }) })

其中sorted_items在图像中打印,由递归函数生成。

为什么会这样,我怎样才能让事情按预期发挥作用?

修改:使用较小的列表似乎有效:

Started POST "/projects" for 127.0.0.1 at 2013-12-11 21:01:08 -0200 Processing by ProjectsController#create as */* Parameters: {"{\"sortd_items\":"=>{"\"2\","=>{"\"5\","=>[{",\"6\","=>[{",\"7\","=>[{",\"8\","=>[{",\"3\","=>{"\"10\","=>[{",\"10\","=>[{",\"4\","=>[{",\"5\","=>[{",\"6\","=>[{",\"7\","=>[{",\"8\","=>[{",\"3\","=>{"\"10\","=>[{",\"10\","=>[{",\"4\","=>[{",\"9\","=>{"\"11\","=>[{",\"12\","=>{"\"13\","=>[{",\"14\","=>[{",\"15\","=>[{",\"13\","=>[{",\"14\","=>[{",\"15\","=>[{",\"11\","=>[{",\"12\","=>{"\"13\","=>[{",\"14\","=>[{",\"15\","=>[{",\"13\","=>[{",\"14\","=>[{",\"15\","=>[{"}"=>nil}]}]}]}]}]}]}}]}]}]}]}]}]}]}}]}}]}]}]}}]}]}]}]}]}]}]}}]}]}]}]}}} Completed 400 Bad Request in 1ms

但我也需要使用大型列表。

2 个答案:

答案 0 :(得分:1)

Rack utils.rb方法to_params_hash确实是递归的。这样做是因为,根据http://api.jquery.com/jQuery.ajax/$.ajax()data:变量视为包含URL查询参数的字符串。

放在一起,Rails会将嵌套结构中的每个键视为您希望在params哈希中看到的内容。你没有;你只需要将所有JSON作为一个字符串传递,所以你自己的方法可以安全地将它解码为JSON,使用一个(可能)不会滥用堆栈的C JSON库。

Per jQuery ajax data two variables,您可以将字符串填充到散列中并传递散列:

var dataObj = {};
dataObj[json]=JSON.stringify({ sortd_items: sorted_items });
$.ajax({ ... data: dataObj });

现在$.ajax()不会看到字符串,也不会将其转换为查询参数,也不会破坏Rack。

答案 1 :(得分:1)

我认为这是正确设置ajax请求中的标头的问题。您可以发布已经通过JSON.stringify的数据,但服务器将不知道如何处理它,除非您告诉它它正在获得什么。这应该解决它:

$.ajax({
  type: 'POST',
  url: '/projects',
  contentType: 'json',
  data: JSON.stringify({ sortd_items: sorted_items })
})