Rails嵌套路由表单仅支持POST,无法生成PUT更新表单问题
Rails嵌套路由下表单partial同时支持新建与编辑的解决方案
问题根源
当前表单partial中固定调用post.comments.build生成新的Comment实例,无论新建还是编辑场景,form_with都会识别为创建操作,因此生成POST请求路径posts/:post_id/comments,而非编辑所需的PUT/PATCH请求路径posts/:post_id/comments/:id。
具体修改步骤
1. 调整表单partial的参数传递逻辑
将partial改为接收外部传入的comment实例,不再在partial内部生成新实例,让partial同时兼容新建和编辑场景。
修改后的表单partial代码:
<%= form_with model: [post, comment] do |f| %> <div class="form-item-box"> <%= f.label :content %> <%= f.text_field :content %> <% comment.errors.full_messages_for(:content).each do |error_message| %> <div class="warning-box"> <%= error_message %> </div> <% end %> <%= f.submit %> </div> <% end %>
注:移除了手动添加的
hidden_field :post_id,因为嵌套路由的model: [post, comment]会自动传递post_id参数,无需冗余代码。
2. 修正控制器edit方法
编辑场景需要先获取要修改的Comment实例,补充控制器代码:
def edit @post = Post.find(params[:post_id]) @comment = @post.comments.find(params[:id]) # 新增:获取目标评论实例 end
3. 分别调整新建/编辑页面的partial渲染调用
- 新建场景(比如在
posts/show页面渲染新建表单):<%= render partial: "form", locals: { post: @post, comment: @post.comments.build } %> - 编辑场景(当前编辑页面):
<%= render partial: "form", locals: { post: @post, comment: @comment } %>
原理说明
Rails的form_with会根据传入的model实例是否已持久化(persisted?方法返回值)自动判断请求行为:
- 若为新实例(新建场景):生成POST请求到
posts/:post_id/comments - 若为已保存的实例(编辑场景):生成PATCH/PUT请求到
posts/:post_id/comments/:id
通过将comment实例作为外部参数传入partial,实现了同一个模板复用处理新建和编辑逻辑,符合DRY原则。
内容的提问来源于stack exchange,提问作者nicecoding521235
相关产品推荐
相关产品推荐

