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

Rails控制器多循环创建方法报错:undefined method `each' for nil:NilClass

问题分析

  1. undefined method 'each' for nil:NilClass错误:当某个时间范围未选择任何日期时,value[:days]为nil,直接调用each触发报错。
  2. 无效日程ID:传入的schedule_ids包含空字符串"",会生成无关联日程的无效记录。
  3. 记录保存不完整:循环中每次覆盖@scheduleevent变量,最终仅保存最后一条记录,前面的实例未执行保存操作。

修复步骤

1. 修正创建方法逻辑

修改create方法,过滤无效数据、处理nil情况,同时确保所有记录都被保存:

def create
  # 过滤掉空的日程ID
  valid_schedule_ids = scheduleevent_params[:schedule_ids].reject(&:blank?)
  # 追踪所有记录的保存状态
  all_saved = true

  valid_schedule_ids.each do |schedule_id|
    scheduleevent_params[:schedtimeranges_attributes].each do |key, value|
      # 跳过无日期的时间范围
      next unless value[:days].present?

      value[:days].each do |day|
        @scheduleevent = Scheduleevent.new(
          schedule_id: schedule_id,
          day: day,
          title: scheduleevent_params[:title],
          description: scheduleevent_params[:description],
          start_date: scheduleevent_params[:start_date],
          end_date: scheduleevent_params[:end_date],
          start_time: value[:start_time],
          end_time: value[:end_time],
          user_id: current_user.id
        )
        # 记录保存失败的情况
        all_saved = false unless @scheduleevent.save
      end
    end
  end

  respond_to do |format|
    if all_saved
      format.turbo_stream
      format.html { redirect_to scheduleevents_url, notice: "所有日程事件已成功创建。" }
      format.json { render json: { message: "所有日程事件已成功创建" }, status: :created }
    else
      format.html { render :new, status: :unprocessable_entity }
      format.json { render json: @scheduleevent.errors, status: :unprocessable_entity }
    end
  end
end

2. 确认参数许可配置

确保scheduleevent_params正确允许嵌套的days数组参数:

def scheduleevent_params
  params.require(:scheduleevent).permit(
    :title, :day, :start_time, :end_time, :description, 
    :start_date, :end_date, :repeattypeid, :hexcolor, 
    :scheduleinstid, :locked,
    schedule_ids: [],
    schedtimeranges_attributes: [ 
      :id, :start_time, :end_time, :repeattype, :_destroy, 
      days: []
    ]
  )
end

3. 前端可选优化(避免空提交)

在表单提交前添加验证,确保每个时间范围至少选择一个日期,比如在Stimulus控制器中添加逻辑:

// app/javascript/controllers/nested_form_controller.js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  submit(event) {
    const wrappers = this.element.querySelectorAll('.nested-form-wrapper')
    let isValid = true

    wrappers.forEach(wrapper => {
      const days = wrapper.querySelectorAll('input[name*="[days]"]:checked')
      if (days.length === 0) {
        isValid = false
        alert('每个时间范围至少选择一个日期')
      }
    })

    if (!isValid) event.preventDefault()
  }
}

然后在表单标签添加data-action="submit->nested-form#submit"。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 09:55:21