14

我是 Rails 的新手,并试图通过复选框和使用 jquery ajax 来更改布尔值:

<%- @tasks.each do |task| %>
  <div class="task-wrapper">
    <%= check_box_tag 'completed', task.id , task.completed, :class => "task-check" %>
    <%= content_tag :span, task.task %>
    <%= content_tag :span, task.deadline %>
  </div>
<% end %>

和javascript:

$(".task-check").bind('change', function(){
  if (this.checked){
    var bool = this.checked ? 1 : 0;
    $.ajax({
      url: '/todos/toggle',
      type: 'POST',
      data: '{"task_id":"'+ this.value +'", "bool":"'+ bool +'"}'
    });
  }
  else {
    alert("no");
  }
});

然后控制器:

def toggle(task_id, bool)
  @task = Todo.find_by_id(task_id)

  if @task != nil?
    @task.update_attributes(:completed => bool)
  else
    set_flash "Error, please try again"
  end
end

最后是路线:

resources :todos do
  member do
    post 'toggle'
  end
end

也尝试了收集,但给出了同样的错误。

每当我尝试它时,我都会404 error采取行动。

问题是什么?

谢谢

4

2 回答 2

43

从 Rails 4 开始,有一种方法可以做到这一点,而无需任何额外的 JS 或 CSS:

<%= check_box_tag 'completed', task.id, task.completed,
      data: {
        remote: true,
        url: url_for(action: :toggle, id: task.id),
        method: "POST"
      } %>

事实证明,添加remote: true到输入会导致 jquery-ujs 以所有不错的方式使其成为 ajax-y。Thoughtbot 的“A Tour of Rails jQuery UJS”简要介绍了这一点(以及许多其他可用的好东西);jQuery UJS wiki 中的“Unobtrusive scripting support for jQuery”页面在这方面也做了彻底的工作。

于 2016-01-07T00:44:10.470 回答
16

尝试以下操作(保留其他所有内容):

的JavaScript:

$(".task-check").bind('change', function(){
  if (this.checked){
    $.ajax({
      url: '/todos/'+this.value+'/toggle',
      type: 'POST',
      data: {"completed": this.checked}
    });
  }
  else {
     alert("no");
  }
});

控制器:

def toggle
  @task = Todo.find(params[:id])

  if @task.update_attributes(:completed => params[:completed])
    # ... update successful
  else
    # ... update failed
  end
end

看看bundle exec rake routes向您展示 rails 生成的路径。如果您post 'toggle'是成员,您将获得类似的路径/todos/:id/toggle,因此在 ajax 中更新了 url。

在控制器中,:id来自路径的最终位于params[:id]. 来自 ajax 请求的数据也以params散列结束,因此params[:completed].

于 2013-03-22T14:50:53.383 回答