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

Rails测验应用question_id未随用户答题选择正确更新问题

问题说明

开发Rails测验应用时,提交答题结果后question_id字段始终存储为最后一道题的ID(当前场景为11),无法匹配用户实际作答的题目ID,其余user_choice、user_id字段存储正常。

现有代码结构

  • 三个核心模型:question.rb、user.rb、result.rb

Question模型代码

class Question < ApplicationRecord
    validates :question, presence: true
    validates :option1, presence: true 
    validates :option2, presence: true 
    validates :option3, presence: true 
    validates :option4, presence: true 
    validates :answer, presence: true
end

Question表迁移文件

class CreateQuestions < ActiveRecord::Migration[6.1]
  def change
    create_table :questions do |t|
      t.text :question
      t.text :option1
      t.text :option2
      t.text :option3
      t.text :option4
      t.text :answer
      t.timestamps
    end
  end
end

Result表迁移文件

class CreateResults < ActiveRecord::Migration[6.1]
  def change
    create_table :results do |t|
      t.text :user_choice
      # 实际包含question_id、user_id两个外键
      t.timestamps
    end
  end
end

Result控制器代码

class ResultController < ApplicationController
  def create
    @result=Result.create(
      user_choice: params[:user_choice], 
      question_id: params[:question_id], 
      user_id: current_user.id
    )
  end
end

答题页视图(view/question/index)代码

<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 model: @result ,url: result_path do |f| %>
   <% @questions.each do |question| %>
    <div>
        <%= f.hidden_field :question_id, value: question.id %>
          <%= f.hidden_field :user_id, value: current_user.id %>
        <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 %>
                <%= f.label :user_choice, c  %>
            </div>
        <% end %>
    </div>&nbsp;&nbsp;
<% end %>
       <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>
  </div>
</div>

问题根因
  1. 你在@questions.each循环中重复渲染了name属性相同的question_id隐藏输入框。HTML表单提交同名参数时,只会保留最后一个输入项的值,因此后端拿到的params[:question_id]永远是循环到最后一道题的ID。
  2. 你当前的单选框命名为user_choice[#{question.id}],提交后params[:user_choice]本身就是以题目ID为键、用户选择的选项为值的哈希结构,原有控制器单次创建一条Result记录的逻辑,本身也不匹配一次提交多道题答案的业务场景。
  3. 之前user_id能正常存储,是因为循环里所有隐藏域的user_id值都是当前用户ID,哪怕取最后一个值也不会出错,但这种把用户ID放在前端传参的方式有被篡改的风险,不推荐使用。

修复方案

第一步:修正视图层代码

删掉循环里重复的question_id、user_id隐藏域,同时修正单选框label的绑定关系(原有label点击无法选中对应单选框),修正后的表单部分代码:

<%= form_with model: @result ,url: result_path do |f| %>
  <% @questions.each do |question| %>
  <div>
    <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 %>
            <%= f.label :"user_choice[#{question.id}]", c  %>
        </div>
    <% end %>
  </div>&nbsp;&nbsp;
  <% end %>
  <div class="sub"> <%= f.submit "Submit", class:"btn btn-primary" %></div>
<% end %>

第二步:修正控制器create逻辑

遍历params[:user_choice]哈希,为每道题的作答单独创建Result记录,直接从哈希key取题目ID,user_id直接从后端current_user取,完全不依赖前端传参:

class ResultController < ApplicationController
  def create
    # 遍历所有题的作答,逐题存储结果
    params[:user_choice].each do |question_id, selected_choice|
      Result.create(
        user_choice: selected_choice,
        question_id: question_id,
        user_id: current_user.id
      )
    end
    # 按需添加跳转、提示逻辑
    redirect_to results_path, notice: "答题提交成功"
  end
end

额外优化建议

在Result模型里补全关联和参数校验,避免脏数据:

# result.rb
class Result < ApplicationRecord
  belongs_to :user
  belongs_to :question
  validates :user_choice, presence: true
end

同时在Question、User模型中补全反向关联:

# question.rb
has_many :results

# user.rb
has_many :results

内容的提问来源于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 10:57:18