我有一个非常令人沮丧的问题。这是流程:
我有一个模型项目和模型测试。项目有很多测试。
在项目的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控制台之后,我发现了以下细节。
如果我在进入页面时已经存在的表单上点击“更新测试”,这就是您对表单数据的看法:
该呼叫返回200成功。
但是,如果我按照上面的步骤通过JS动态添加的表单上点击Update Test,它会显示:
那个失败了404没找到。
为什么表单在第二种情况下不使用_patch? This answer表示如果对象被持久化,表单应该使用PUT,并且我已经在我的rails控制台中确认该对象实际上是持久的。
答案 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
如果您不将其添加为自定义路线,则无法找到它。
要解决此问题,请明确指定更新表单中的方法。或者在此发布您的表单。