Rails项目中questions/show.html.erb嵌套表单无法保存数据至数据库
我来帮你捋捋这个问题哈,你现在是想在已存在的Question详情页创建关联的Answer,结果提交时出现参数异常,大概率是路由、控制器逻辑或者表单设置没匹配上场景,咱们一步步来修正:
1. 先确认路由设置(关键第一步)
因为是给已存在的Question添加Answer,需要用嵌套路由来关联两者。修改你的config/routes.rb:
resources :questions do resources :answers, only: [:create] # 只需要create动作来提交新回答 end
这样提交Answer的请求路径会是POST /questions/:question_id/answers,Rails会自动把question_id传到参数里。
2. 调整控制器逻辑
你之前可能错误地在QuestionsController里处理Answer的创建,但实际上应该单独用AnswersController来处理:
首先更新QuestionsController的show动作
在展示Question的时候,初始化一个关联的空Answer实例,供表单使用:
# app/controllers/questions_controller.rb def show @question = Question.find(params[:id]) @answer = @question.answers.build # 初始化和当前question绑定的空answer end
新建/完善AnswersController
创建专门处理Answer创建的控制器:
# app/controllers/answers_controller.rb class AnswersController < ApplicationController def create # 先找到对应的question @question = Question.find(params[:question_id]) # 用question关联的方法构建answer,自动绑定question_id @answer = @question.answers.build(answer_params) if @answer.save redirect_to @question, notice: '回答创建成功啦!' else # 如果保存失败,回到question展示页显示错误 render 'questions/show' end end private # 许可answer的参数,替换成你的Answer模型实际需要的属性(比如content、author等) def answer_params params.require(:answer).permit(:content) end end
3. 修正show页面的表单
你之前可能用了嵌套表单(比如fields_for :answers),但那是创建Question同时批量创建Answer的场景,现在是单独创建Answer,所以直接针对@answer构建表单即可:
如果用simple_form的话,修改app/views/questions/show.html.erb:
<h1><%= @question.title %></h1> <p><%= @question.body %></p> <h3>添加新回答</h3> <%= simple_form_for [@question, @answer] do |f| %> <%= f.error_notification %> <!-- 显示表单错误提示 --> <%= f.input :content, label: '你的回答' %> <!-- 替换成你的Answer属性 --> <%= f.button :submit, '提交回答' %> <% end %> <!-- 展示已有的回答 --> <h3>所有回答</h3> <% @question.answers.each do |answer| %> <div class="answer"> <p><%= answer.content %></p> </div> <% end %>
为什么之前会出现参数异常?
你之前可能是在给Question的表单嵌套Answer字段,导致提交的参数结构是question[answers_attributes][...]),但实际上我们要提交的是单独的answer[...])参数,并且需要带上question_id来关联已存在的Question。调整后参数结构就会符合Rails的预期,不会再出现异常。
内容的提问来源于stack exchange,提问作者Erik Torres

