使用turbolinks时,获取无路由匹配[POST]

时间:2014-05-07 11:31:43

标签: ruby-on-rails turbolinks

我有待办事项列表应用。在应用程序中,您可以通过单击复选框来标记待办事项。

这是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 %>

这里是js

$(document).on('click', ".dashboard_done_box", function(){
 $("#edit_todo_" + $(this).attr('id')).submit()
});

routes.rb有一行

resources :todos

当我刷新页面时,它可以工作,但是当我导航到它时,我收到了这个错误。

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"):

当我停用 turbolinks 时,它也有效。

此代码适用于我的应用程序中的其他页面,它只在一个页面上我遇到此问题。

当它工作时发出PATCH请求

Started PATCH "/todos/1" for 127.0.0.1 at 2014-05-07 13:44:08 +0200
Processing by TodosController#update as JS

为什么它会执行POST请求以及它如何连接到turbolinks?

更新

Yosep Kim建议我应该制作一个后期路线

的routes.rb

post 'todos/:id'  => 'todos#update', :as => :todo_update

表格

<%= form_for @todo, remote: true, url: todo_update_path(@todo), method: :post do |f| %>

现在我得到了控制器,但只有这些参数

{"controller"=>"todos", "action"=>"update", "id"=>"3"}

结论:表单提交未进行序列化。为什么呢?

3 个答案:

答案 0 :(得分:2)

表单是如何呈现的?

Rails使用PATCH谓词进行更新,因为在rails应用程序中,更新几乎总是部分更新。 PUT动词应该用于完整更新(比如覆盖文件时)在这里阅读更多Riding With Rails

Rails使用隐藏字段来容纳html动词。

您的表单应该像这样呈现

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

请注意表格中是否有表格。该表可能会使表单呈现奇怪。

答案 1 :(得分:2)

最新的64位Chrome开发/测试频道版本37,38上有一个错误。

如果您使用它,请参阅https://code.google.com/p/chromium/issues/detail?id=388664

答案 2 :(得分:1)

首先,当单击复选框时,您的代码将创建两个冗余请求。第一个是由表单触发的,第二个是由你的JS代码触发的。表单触发的那个在页面刷新后只能工作一次。一旦你点击它,Turbolink将刷新BODY中的内容而不重新加载DOM,无法将AJAX事件处理程序附加到表单。

您可以使用preventDefault来抑制默认行为。这应该只通过JS代码触发一次动作。

$(document).on('click', ".dashboard_done_box", function(e){
 e.preventDefault();
 $("#edit_todo_" + $(this).attr('id')).submit()
});