Rails项目提交表单报错No route matches [POST] "/page/new"排查
这个错误的核心是表单提交的目标路径不匹配路由规则,具体来看有两个关键问题:
1. 表单的form_with配置错误
你在new.html.erb里用了scope: :pages,但你的资源定义是单数的page,更关键的是没有绑定到@page实例——Rails的form_with如果绑定了模型实例,会自动根据实例状态(新建/已保存)生成正确的提交路径和HTTP方法。
现在你的表单会尝试提交到/page/new这个路径,但从rails routes的输出能看到,POST请求的合法目标是/page(对应page#create),而/page/new只接受GET请求(用来渲染表单),这就导致了路由匹配失败。
2. 路由资源名不符合Rails惯例(可选但建议修正)
你在routes.rb里用了单数的resources :page,虽然Rails能处理,但这不符合Rails的RESTful惯例,通常资源名应该用复数resources :pages,对应的控制器也应该命名为PagesController(复数),这样生成的路由路径会是/pages,更符合社区通用规范。
具体修复步骤:
第一步:修正表单代码
把new.html.erb里的表单改成绑定到@page实例,去掉错误的scope配置:
<%= form_with model: @page, local: true do |form| %> <%= form.label "Name" %></br> <%= form.text_field :name %></br> <%= form.label "Description" %></br> <%= form.text_field :description %></br> <%= form.label "GitHub" %></br> <%= form.text_field :github %></br> <%= form.label "Website" %></br> <%= form.text_field :website %></br></br> <%= form.submit "Add" %></br> <% end %>
修改后,form_with会自动识别@page是新建实例,将表单的提交路径设置为/page(POST请求),正好匹配路由里的page#create动作。
第二步:(可选但推荐)修正路由与控制器命名
如果想遵循Rails最佳实践:
- 把
routes.rb里的resources :page改成:
Rails.application.routes.draw do resources :pages end
- 把控制器文件从
page_controller.rb重命名为pages_controller.rb,同时修改控制器类名:
class PagesController < ApplicationController # 内部代码保持不变,仅类名改为复数 end
- 对应的视图文件夹从
app/views/page重命名为app/views/pages。
这样修改后,路由会变成更规范的复数形式(比如/pages、/pages/new等),也更符合Rails开发者的通用习惯。
验证方法:修改表单后,刷新/page/new页面,查看页面源码里的form标签action属性,应该会显示为/page(如果用了复数路由则是/pages),此时提交表单就能正确触发create动作,不会再出现路由匹配错误了。
内容的提问来源于stack exchange,提问作者Przemek

