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

如何为Rails测验应用的Replies控制器Create动作实现30分钟超时处理?

嘿,针对你这个测验应用的定时需求,我整理了几个实用的实现思路,结合Rails后端和前端来搞定:

方案一:前端定时自动触发Create动作(适合需要自动提交的场景)

如果允许自动提交(哪怕是空参数),可以通过前端定时器在30分钟后模拟表单提交或直接发送请求到Create接口:

  • 步骤1:在测验页面添加定时逻辑
    在你的测验视图页面(比如quizzes/show.html.erb)里加入JavaScript定时器:

    document.addEventListener('DOMContentLoaded', function() {
      // 设置30分钟后执行的定时器(单位:毫秒)
      setTimeout(function() {
        // 优先尝试提交现有表单
        const quizForm = document.getElementById('quiz-submit-form');
        if (quizForm) {
          quizForm.submit();
        } else {
          // 没有表单的话,用Fetch API直接发送POST请求到replies#create
          fetch('/replies', {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
              // 必须带上Rails的CSRF令牌,否则会被拦截
              'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content
            },
            body: JSON.stringify({
              reply: { answer_ids: [] } // 空参数,需要后端处理
            })
          }).then(() => {
            // 提交后重定向到首页或结果页
            window.location.href = '/';
          });
        }
      }, 30 * 60 * 1000);
    });
    
  • 步骤2:后端处理空参数的提交
    在replies_controller.rb的Create动作里,处理空参数的情况:

    def create
      @reply = current_user.replies.build(reply_params)
      
      # 如果没有提交任何答案,标记为自动提交状态
      if @reply.answer_ids.blank?
        @reply.status = 'auto_submitted'
      end
    
      if @reply.save
        redirect_to quiz_results_path, notice: '测验已自动提交'
      else
        # 保存失败的话直接重定向首页
        redirect_to root_path, alert: '自动提交失败,请稍后重试'
      end
    end
    
    private
    
    def reply_params
      params.require(:reply).permit(answer_ids: [])
    end
    
方案二:前端定时提示/强制重定向(如果不允许空参数提交)

如果空参数提交不可行,那可以在30分钟后给用户提示,或者直接强制重定向到首页:

document.addEventListener('DOMContentLoaded', function() {
  setTimeout(function() {
    // 先弹出提示框询问用户
    const confirmSubmit = confirm('测验时间已到,请提交答案或返回首页');
    if (confirmSubmit) {
      document.getElementById('quiz-submit-form').submit();
    } else {
      // 用户取消则重定向首页
      window.location.href = '/';
    }

    // 也可以直接不提示,强制重定向
    // window.location.href = '/';
  }, 30 * 60 * 1000);
});
关键补充:后端兜底验证(防止前端作弊)

前端定时器很容易被用户通过浏览器控制台篡改或取消,所以一定要在后端加一层时间验证:

  • 步骤1:记录用户开始测验的时间
    在进入测验页面的控制器动作里(比如quizzes#show),把开始时间存入session:

    def show
      @quiz = Quiz.find(params[:id])
      # 记录开始时间到session
      session[:quiz_start_time] = Time.now
    end
    
  • 步骤2:在Create动作里校验时间

    def create
      # 取出session里的开始时间,判断是否超过30分钟
      start_time = session[:quiz_start_time]
      if start_time.present? && (Time.now - start_time) > 30.minutes
        redirect_to root_path, alert: '测验时间已过期,请重新开始'
        return
      end
    
      # 后续的Create逻辑...
    end
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 09:16:45