【问题标题】:Rails AJAX With check_box_tag Throwing 404 Error On Click带有 check_box_tag 的 Rails AJAX 单击时抛出 404 错误
【发布时间】:2013-06-06 16:43:02
【问题描述】:

这是我第一次使用 Rails 的 AJAX 助手。我让 AJAX 删除可以在远程 true 下正常工作,但我现在遇到的问题是 check_box_tag。在其他一些 SO Q&A 的帮助下,我正在尝试设置一个非常基本的待办事项列表,其中每个任务都有一个复选框。当用户单击复选框时,它应该通过称为“完成”的方法发送 AJAX PUT 请求并更新该任务的相应数据库列,使用真或假,然后不呈现任何内容。

所以我遇到了两个问题:
现在数据库没有更新,当我点击一个复选框时,在 Chrome 控制台中它显示 404 错误。

Stacktrace 显示“找不到 id=undefined 的项目”:

Started PUT "/projects/undefined/tasks/61/completed/" for 127.0.0.1 at 2013-06-10 16:55:55 -0500
Processing by TasksController#completed as HTML
Parameters: {"id"=>"61", "completed"=>"true", "project_id"=>"undefined"}
Project Load (0.2ms)  SELECT "projects".* FROM "projects" WHERE "projects"."id" = ? LIMIT 1  [["id", "undefined"]]
Completed 404 Not Found in 3ms

ActiveRecord::RecordNotFound (Couldn't find Project with id=undefined):
app/controllers/tasks_controller.rb:68:in `completed'

我正在使用嵌套资源,因为项目通过 ProjectTasks 等有许多任务,所以我想知道问题是否在这个区域的某个地方。我的自定义路由与其他路由匹配相同的格式,所以我很困惑为什么它未定义并且 ajax 回调没有处理。

routes.rb:

resources :projects do
  resources :tasks
end

put 'projects/:project_id/tasks/:id/completed' => 'tasks#completed'

rake 路线:

root        /                                                   projects#index
project_tasks GET    /projects/:project_id/tasks(.:format)               tasks#index
              POST   /projects/:project_id/tasks(.:format)               tasks#create
new_project_task GET    /projects/:project_id/tasks/new(.:format)           tasks#new
edit_project_task GET    /projects/:project_id/tasks/:id/edit(.:format)      tasks#edit
project_task GET    /projects/:project_id/tasks/:id(.:format)           tasks#show
              PUT    /projects/:project_id/tasks/:id(.:format)           tasks#update
              DELETE /projects/:project_id/tasks/:id(.:format)           tasks#destroy
projects GET    /projects(.:format)                                 projects#index
              POST   /projects(.:format)                                 projects#create
new_project GET    /projects/new(.:format)                             projects#new
edit_project GET    /projects/:id/edit(.:format)                        projects#edit
      project GET    /projects/:id(.:format)                             projects#show
              PUT    /projects/:id(.:format)                             projects#update
              DELETE /projects/:id(.:format)                             projects#destroy
              PUT    /projects/:project_id/tasks/:id/completed(.:format) tasks#completed

tasks_controller.rb:

def completed
  @project = Project.find(params[:project_id])
  @task = @project.tasks.find(params[:id])

  respond_to do |format|
    if @task.update_attributes(params[:task])
      format.html { redirect_to(project_tasks_path(@project.id)) }
      format.js   { render :nothing => true }
    end
  end
end

_task.html.erb:

<ul>
  <% @tasks.each do |task| %>
    <li>
      <%= check_box_tag task.id, task.completed ? 'false' : 'true', task.completed, :url => url_for(:action => 'completed', :id => task.id) %>
      <%= task.name %>
      <%= link_to 'Edit', edit_project_task_path(@project.id, task.id) %> |
      <%= link_to 'Delete', project_task_path(@project.id, task.id), confirm: "Are you sure you want to delete this task?", method: :delete, remote: true, class: 'delete_task' %>
    </li>
  <% end %>
</ul>

tasks.js.coffee:

$ ->
  $('input:checkbox').change ->
    checked = undefined
    if $(this).is(":checked")
      checked = true
    else
      checked = false
    $.ajax
      type: "PUT"
      url: "/projects/" + $(this).attr('project_id') + "/tasks/" + $(this).attr('id') + "/completed/"
      dataType: "html"
      data:
        id: $(this).attr('id')
        completed: checked
      success: (data, textStatus, jqXHR) ->
        alert("Task has been marked as completed!")

$ ->
  $('input:checkbox').change ->
    if ( $(this).is(':checked') )
      $(this).parent().addClass('marked')
    else
      $(this).parent().removeClass('marked')

我们将不胜感激任何正确方向的帮助。

【问题讨论】:

    标签: ruby-on-rails ajax checkbox


    【解决方案1】:

    我能够弄清楚这一点。然而,这可能不是最干净的 Rails 方式。我需要将项目 id 传递给 url,这在早期很明显,并且还使用 data-url 属性将此信息传递给 javascript。

    _tasks.html.erb

    <%= check_box_tag task.id, task.completed ? 'false' : 'true', task.completed, 'data-url' => url_for(:action => 'completed', :project_id => @project.id, :id => task.id) %>
    

    然后将其分配给一个变量并返回带有 .js 的 url。这导致修复了 404 问题。

    tasks.js.coffee

    $ ->
      $('input:checkbox').change ->
        checked = undefined
        url = $(this).data("url")
        if $(this).is(":checked")
          checked = true
        else
          checked = false
        $.ajax
          type: "PUT"
          url: url + ".js"
          data:
            id: $(this).attr('id')
            completed: checked
    

    通过完成方法更新数据库列,我需要引用相应的列。

    tasks_controller.rb

    def completed
      @project = Project.find(params[:project_id])
      @task = @project.tasks.find(params[:id])
    
      respond_to do |format|
        if @task.update_attributes(:completed => params[:completed])
          format.html { redirect_to(@task) }
          format.js   { render :nothing => true }
        end
      end
    end
    

    现在,当用户选中或取消选中复选框时,该任务在数据库中被标记为已完成(true 或 false),而无需刷新页面。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-22
      • 1970-01-01
      • 2015-09-28
      • 1970-01-01
      • 2018-01-16
      • 2021-09-27
      • 2019-04-12
      相关资源
      最近更新 更多