You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails提交多选题答案时所有记录question_id为最后一题ID如何解决

Rails多选题答题功能数据保存异常修复方案

问题现象

开发Ruby on Rails多选题答题功能时,提交答卷后所有用户答题记录关联的question_id均为最后一道试题的ID(如共12道题时所有记录的question_id都为12);尝试使用fields_for嵌套属性写法时,页面无报错但后端不会保存任何答题数据。
问题效果截图

问题根因

  • 视图层逻辑错误:循环渲染试题时,重复生成同名question_id隐藏域,循环到最后一题时会将所有之前隐藏域的值覆盖为最后一题ID,是导致question_id全部异常的直接原因。
  • 后端逻辑错误:原有ResultController#create每次请求仅创建1条Result记录,但一次表单提交包含多道题的作答数据,无法批量保存所有答题结果。
  • fields_for用法错误:未在模型层配置嵌套属性接收规则、未放开对应参数白名单、传入fields_for的参数为全量试题集合而非单题关联对象,生成的参数格式不符合Rails嵌套属性要求,导致无数据保存。

修复步骤

1. 确认模型关联关系

首先保证三个模型的关联配置正确:

  • app/models/user.rb
class User < ApplicationRecord
  # 保留原有Devise等配置代码
  has_many :results, dependent: :destroy
end
  • app/models/question.rb
class Question < ApplicationRecord
  has_many :results, dependent: :destroy
  # 保留原有试题字段相关逻辑
end
  • app/models/result.rb
class Result < ApplicationRecord
  belongs_to :user
  belongs_to :question
end

2. 修正控制器逻辑

首先遵循Rails控制器命名规范,将原ResultController重命名为复数形式ResultsController,对应路由配置调整为resources :results,避免路由匹配错误。

  • 修正QuestionsController,在列表页初始化表单所需对象:
class QuestionsController < ApplicationController
  def index
    @questions = Question.all
    @result = Result.new
  end

  def new
    @question = Question.new 
  end

  def create
    @question = Question.new(question_params)
    if @question.save
      flash[:success] = "Question saved successfully"
      redirect_to questions_url, notice: "Successfully created question"
    else
      render :new 
    end    
  end

  private
  def question_params
    params.require(:mc_question).permit(:question, :option1, :option2, :option3, :option4, :answer)
  end
end
  • 重写ResultsController#create逻辑,支持批量保存多题作答,加入事务保证数据一致性,同时移除前端传用户ID的逻辑,直接从登录态取用户ID避免参数篡改:
class ResultsController < ApplicationController
  def create
    unless current_user
      redirect_to new_user_session_path, alert: "请先登录后再答题"
      return
    end

    begin
      ActiveRecord::Base.transaction do
        # 提交后的user_choice参数格式为 { "题目ID" => "用户选择的选项", ... }
        params[:user_choice].each do |question_id, selected_option|
          next if selected_option.blank? # 跳过未作答的题目
          Result.create!(
            user_id: current_user.id,
            question_id: question_id,
            user_choice: selected_option
          )
        end
      end
      redirect_to questions_path, notice: "答卷提交成功"
    rescue ActiveRecord::RecordInvalid => e
      redirect_to questions_path, alert: "提交失败:#{e.message}"
    end
  end
end

3. 修正视图层表单代码

删除错误的循环fields_for和冗余的question_id、user_id隐藏域,修正单选按钮的label关联,避免点击label无法选中选项的问题:

<div class="card o-hidden border-0 shadow-lg my-5">
  <div class="card-body ">
    <!-- Nested Row within Card Body -->
    <div class="row py-5">
      <div class="p-5">
        <div class="text-center">
          <h1 class="h4 text-gray-900 mb-4 ">Multiple-Choice Questions</h1>
        </div>

        <%= form_with url: results_path, method: :post do |f| %>
          <%= render "devise/shared/error_messages", resource: current_user %>
          <% @questions.each do |question| %>
            <p><%= question.question %></p>
            <% choices = [question.option1, question.option2, question.option3, question.option4] %>
            <% choices.each do |c| %>
              <div>
                <%= f.radio_button "user_choice[#{question.id}]", c, id: "choice_#{question.id}_#{c.parameterize}" %>
                <%= f.label "choice_#{question.id}_#{c.parameterize}", c  %>
              </div>
            <% end %>
          <% end %>
          &nbsp;&nbsp;
       
          <div class="sub">
            <%= f.submit "Submit", class:"btn btn-primary" %>
          </div>
        <% end %>

        <div class="para1">
          <%= link_to 'New Question', new_question_path,class:"btn btn-primary btn-user" %>
        </div>
      </div>
    </div>
  </div>
</div>

补充说明

如果后续需要用fields_for嵌套属性实现,需要额外在模型层添加accepts_nested_attributes_for配置、在控制器参数白名单中放开嵌套属性权限、调整表单传入fields_for的对象为关联集合,相比当前直接遍历参数哈希的实现方式更复杂,适合需要同时提交主对象+关联子对象的场景,当前批量答题场景用遍历哈希的方案更简洁易维护。


内容的提问来源于stack exchange,提问作者Abu Bakar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 13:48:14