表单提交时,没有路由匹配[POST]

时间:2013-09-11 17:58:06

标签: ruby-on-rails

我有一个非常令人沮丧的问题。这是流程:

我有一个模型项目和模型测试。项目有很多测试。

在项目的show页面中,我按下“添加测试”按钮:

<%= link_to "Add test", new_project_test_path, :remote => true %>

这会调用new中的tests_controller方法:

  def new
    @project = Project.find(params[:project_id])
    @test = Test.new
  end

由于是远程呼叫,之后会调用new.js.erb,其中包含:

$("#tests_table").append("<%= escape_javascript(render 'form', test: @test, project: @project) %>")

这会显示一个表单_form.html.erb,它以:

开头
<%= form_for([@project, test], :remote => true ) do |f| %>

填写表单后,我点击提交按钮(“创建测试”),调用create方法:

  def create
    @project = Project.find(params[:project_id])
    @test = @project.tests.create(test_params)
    end
  end

由于表单是远程的,因此在完成后会调用create.js.erb,其中包含:

$("#tests_table").append("<%= escape_javascript(render 'test', test: @test, project: @project) %>");

这会添加_test.erb.html

的内容
<%= render "tests/form", test: test, project: @project %>

测试行始终处于可编辑状态,这就是_test部分继续再次显示表单的原因。

现在插入的新行包含正确的值,并且提交按钮显示“更新测试”。

但是,当我在这个新插入的表单上点击Update Test时,它没有通过,Javascript控制台显示POST请求失败:

  

没有路线匹配[POST]   “/项目/ 5230920870dbf2ba260000e8 /测试/ 5230ae3970dbf2ec30000239”

这怎么可能?具有该ID的新测试对象存在,这是100%的事实。我可以在rails控制台中检索它。如果我刷新页面然后点击Update Test,它就会通过。但只有当我通过Javascript重新插入行并点击Update Test时,它才会通过。你在这里看到任何看起来阴暗的东西吗?

我的routes.rb有:

resources :projects do 
    resources :tests
end

请记住,我可以对该URL执行POST请求,并且它可以在整页刷新时运行,但是当对象是新的并且使用Javascript动态插入表单时,会发生一些阴影。

相关的佣金路线输出:

          project_tests GET    /projects/:project_id/tests(.:format)                                              tests#index
                        POST   /projects/:project_id/tests(.:format)                                              tests#create
       new_project_test GET    /projects/:project_id/tests/new(.:format)                                          tests#new
      edit_project_test GET    /projects/:project_id/tests/:id/edit(.:format)                                     tests#edit
           project_test GET    /projects/:project_id/tests/:id(.:format)                                          tests#show
                        PATCH  /projects/:project_id/tests/:id(.:format)                                          tests#update
                        PUT    /projects/:project_id/tests/:id(.:format)                                          tests#update
                        DELETE /projects/:project_id/tests/:id(.:format)                                          tests#destroy

更新详情

在检查了JS控制台之后,我发现了以下细节。

如果我在进入页面时已经存在的表单上点击“更新测试”,这就是您对表单数据的看法:

enter image description here

该呼叫返回200成功。

但是,如果我按照上面的步骤通过JS动态添加的表单上点击Update Test,它会显示:

enter image description here

那个失败了404没找到。

为什么表单在第二种情况下不使用_patch? This answer表示如果对象被持久化,表单应该使用PUT,并且我已经在我的rails控制台中确认该对象实际上是持久的。

2 个答案:

答案 0 :(得分:0)

您是否检查了路线文件以确保其设置正确?这就是我设置这样的项目的方式。

resources :projects do
    resources :tests
end

答案 1 :(得分:0)

更新的http动词将是一个PUT。不是POST。

这是用户资源的自动生成路由

POST   /users(.:format)                                          users#create

PUT    /users/:id(.:format)                                      users#update

耙路线| grep测试并查看是否有如下所示的路线

POST /projects/:project_id/tests/:id测试#update

如果您不将其添加为自定义路线,则无法找到它。

要解决此问题,请明确指定更新表单中的方法。或者在此发布您的表单。