Rails 3 向同一 URL 发出 ajax POST,后跟 GET
如下所示,我在 Rails 3.1 应用程序中尝试使用块通过 link_to 进行 POST:
views/wall/_problem.html.erbviews
<li data-icon="check">
<%= link_to(
url_for(
:controller => 'completed_problems',
:action => 'create',
:problem_id => "#{problem.id}"),
{:class => "wall_problem",
:confirm => "Climbed it?",
:remote => true,
:"data-type" => "json",
:method => "POST"}) do %>
<div>stuff</div>
<% end %>
</li>
/wall/show.html.erb
<% content_for :content do %>
<div data-role="content">
<ul data-role="listview">
<%= render :partial => 'problem', :collection => @wall.live_problems.sort %>
</ul>
<% end %>
<script>
$('.wall_problem').live('ajax:success', function() {
alert("Success!");
});
</script>
这个特定的 POST 定向到以下控制器操作:
controllers/completed_problems_controller.rb
class CompletedProblemsController < ApplicationController
# POST /completed_problems
def create
@problem = Problem.find(params[:problem_id]
@completed_problem = @problem.completed_problems.build
if @completed_problem.save
render :json => { }
else
render :json => { :location => root_url}
end
end
end
正如您从下面的日志中看到的,POST 确实成功了,但由于某种原因,应用程序同时对完全相同的 URL 执行了 GET。
日志
Started POST "/completed_problems?problem_id=11" for 127.0.0.1 at 2011-12-11 13:13:06 -0500
Processing by CompletedProblemsController#create as JSON
Parameters: {"problem_id"=>"11"}
# SQL stuff snipped from here
Completed 200 OK in 116ms (Views: 3.0ms | ActiveRecord: 2.6ms)
Started GET "/completed_problems?problem_id=11" for 127.0.0.1 at 2011-12-11 13:13:06 -0500
Processing by CompletedProblemsController#index as HTML
Parameters: {"problem_id"=>"11"}
Rendered completed_problems/index.html.erb within layouts/application (29.6ms)
Completed 500 Internal Server Error in 36ms
该问题的范围听起来确实类似于 jQuery ajax POST 会导致立即 GET 到同一 URL,但这是使用 jquery_ujs,我不相信我留下了任何自定义 jquery 代码。因此,我无法执行添加“return false;”问题中建议的解决方案。
我怀疑问题出在以下三个地方之一:
- 我使用带有块的 link_to 元素的语法不正确
- 我对控制器内请求的处理不正确
- 我以某种方式将我的 jquery_ujs 加倍了(我真的认为这不是真的,但可能在这里)
编辑
缩小问题#1:
我将脚本更改为以下内容,
<script>
$('.wall_problem').live('ajax:beforeSend', function() {
return false;
});
</script>
并发现 POST 现在没有通过,但是GET 完成,确认该问题似乎 AJAX 处理程序正在获取链接并将其作为 POST 正确提交,但没有拦截浏览器提交的 GET。
缩小问题#2:
我一开始并没有提到它,但我正在使用 Jquery-mobile。现在,在将脚本标记恢复到以前的形式,然后禁用 jquery-mobile 时,我再次尝试了该链接,它现在不提交 GET,而是提交 POST。这让我相信 jquery-ujs 和 jquery mobile 与链接交互的方式存在一些问题。
As seen below, I'm in a Rails 3.1 app attempting to POST with a link_to using a block:
views/wall/_problem.html.erb
<li data-icon="check">
<%= link_to(
url_for(
:controller => 'completed_problems',
:action => 'create',
:problem_id => "#{problem.id}"),
{:class => "wall_problem",
:confirm => "Climbed it?",
:remote => true,
:"data-type" => "json",
:method => "POST"}) do %>
<div>stuff</div>
<% end %>
</li>
views/wall/show.html.erb
<% content_for :content do %>
<div data-role="content">
<ul data-role="listview">
<%= render :partial => 'problem', :collection => @wall.live_problems.sort %>
</ul>
<% end %>
<script>
$('.wall_problem').live('ajax:success', function() {
alert("Success!");
});
</script>
This particular POST is directed to the following controller action:
controllers/completed_problems_controller.rb
class CompletedProblemsController < ApplicationController
# POST /completed_problems
def create
@problem = Problem.find(params[:problem_id]
@completed_problem = @problem.completed_problems.build
if @completed_problem.save
render :json => { }
else
render :json => { :location => root_url}
end
end
end
As you can see from the logs below, the POST does succeed as it should, but for some reason the app executes a GET to the exact same URL at the same time.
LOGS
Started POST "/completed_problems?problem_id=11" for 127.0.0.1 at 2011-12-11 13:13:06 -0500
Processing by CompletedProblemsController#create as JSON
Parameters: {"problem_id"=>"11"}
# SQL stuff snipped from here
Completed 200 OK in 116ms (Views: 3.0ms | ActiveRecord: 2.6ms)
Started GET "/completed_problems?problem_id=11" for 127.0.0.1 at 2011-12-11 13:13:06 -0500
Processing by CompletedProblemsController#index as HTML
Parameters: {"problem_id"=>"11"}
Rendered completed_problems/index.html.erb within layouts/application (29.6ms)
Completed 500 Internal Server Error in 36ms
The problem does sound similar in scope to jQuery ajax POST causes an immediate GET to the same URL but this is using jquery_ujs and I don't believe I've left any custom jquery code sitting around. As such, I can't perform the solution suggested in that problem of adding a 'return false;'
I suspect that issue is in one of three places:
- I have incorrect syntax for using the link_to element with a block
- My handling of the request within the controller is incorrect
- I somehow have doubled my jquery_ujs (which I really don't think to be true, but it could be here)
EDIT
Narrowing down the problem #1:
I changed my script to the following,
<script>
$('.wall_problem').live('ajax:beforeSend', function() {
return false;
});
</script>
And discovered that the POST now did not go through, but the GET did, confirming that problem seems to be that the AJAX handler is picking up the link and submitting it as a POST properly, but is not intercepting the GET that the browser submits.
Narrowing down the problem #2:
I did not mention it at first, but I am using Jquery-mobile. Now in restoring the script tag to its previous form and then disabling jquery-mobile, I have tried the link again and it now does not submit the GET but does submit the POST. That leads me to believe that there's some issue with how jquery-ujs and jquery mobile are interacting with the link.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
根据我在上述编辑中包含的信息,我继续测试 Jquery Mobile 并能够解决问题。
首先,我更新到 Jquery Mobile v1.0,它添加了 linkBindingEnabled 全局配置 (http://jquerymobile.com/demos/1.0/docs/api/globalconfig.html):
其次,我将该配置设置为 False:
Based on the info I included in the above edit, I continued down the path of testing Jquery Mobile and was able to solve.
First, I updated to Jquery Mobile v1.0, which adds the linkBindingEnabled global config (http://jquerymobile.com/demos/1.0/docs/api/globalconfig.html):
Second, I set that config to False: