Reputation: 4927
I have todo list app. In the application there are multiple places wher you can mark a todo done by clicking in a checkbox.
This is the erb
<% @todos.each do |todo|%>
<%= form_for todo, remote: true do |f| %>
<%= f.check_box :completed, :class => "dashboard_done_box", :id => todo.id %>
<% end %>
<% end %>
and here's the js
$(document).on('click', ".dashboard_done_box", function(){
$("#edit_todo_" + $(this).attr('id')).submit()
});
The routes.rb has the line
resources :todos
When I refresh the page it works, but when I am navigating to it I get this error.
Started POST "/todos/1" for 127.0.0.1 at 2014-05-07 13:18:45 +0200
ActionController::RoutingError (No route matches [POST] "/todos/1"):
It also works when I disable turbolinks.
This code works on other pages in my application it is just on one page I have this problem.
When it works in makes a PATCH request
Started PATCH "/todos/1" for 127.0.0.1 at 2014-05-07 13:44:08 +0200
Processing by TodosController#update as JS
Why does it do a POST request and how is it connected to turbolinks?
Update
Yosep Kim suggested I should make a post route
routes.rb
post 'todos/:id' => 'todos#update', :as => :todo_update
The form
<%= form_for @todo, remote: true, url: todo_update_path(@todo), method: :post do |f| %>
Now I get trough to the controller, but only with these parameters
{"controller"=>"todos", "action"=>"update", "id"=>"3"}
Conclusion: The form submission is not getting serialized. Why?
Upvotes: 0
Views: 958
Reputation: 10191
There is a bug on latest 64bit Chrome dev/beta channel version 37,38.
If you use it, see https://code.google.com/p/chromium/issues/detail?id=388664
Upvotes: 2
Reputation: 32945
How does the form render?
Rails uses the PATCH verb to update because in rails applications a update is almost always a partial update. The PUT verb should be used for complete updates ( like when you overwrite a file ) Read more here Riding With Rails
Rails uses hidden fields to accommodate the html verb.
Your form should render like this
<form accept-charset="UTF-8" action="/todos/5" class="edit_todo" data-remote="true" id="roster_edit_done_todo_5" method="post">
<div style="display:none">
<input name="utf8" type="hidden" value="✓">
<input name="_method" type="hidden" value="patch">
</div>
<!-- What ever fields you need -->
</form>
Be aware if you have the form in a table. The table might make the form render strange.
Upvotes: 2
Reputation: 2951
First of all, your code is creating two redundant requests, when the checkbox is clicked. The first one is fired by the form, and the second by the JS code you have. The one that is fired by the form would ONLY work one time after the page refreshes. Once you click on it, Turbolink would refresh the contents in the BODY without reloading the DOM, failing to attach the AJAX event handler to the form.
You can suppress the default behavior by using preventDefault. This should only fire the action once through the JS code.
$(document).on('click', ".dashboard_done_box", function(e){
e.preventDefault();
$("#edit_todo_" + $(this).attr('id')).submit()
});
Upvotes: 0