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.
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: