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

更新BusinessHour时,关联WorkingHour存在则更新否则创建的实现

解决方案

要实现更新business_hours时同步处理working_hours(存在则更新、不存在则创建,且确保7天记录齐全),可以通过调整模型验证、嵌套属性配置,以及在控制器中补充逻辑来完成,具体修改如下:

1. 调整模型代码

修改WorkingHour模型

仅在新建记录时检查day是否重复,避免阻止更新操作:

class WorkingHour < ApplicationRecord
  belongs_to :business_hour

  validates :day, inclusion: { in: %w(mon tue wed thu fri sat sun) }

  # 仅在新建记录时校验day唯一性
  validate :validate_day, on: :create

  def validate_day
    if business_hour.working_hours.where(day: self.day).exists?
      errors.add(:day, "has already been added")
    end
  end
end

修改BusinessHour模型

调整嵌套属性配置,支持更新已有记录并过滤空属性:

class BusinessHour < ApplicationRecord
  has_many :working_hours, class_name: "WorkingHour"
  belongs_to :organization
  # 移除update_only,添加空属性过滤规则
  accepts_nested_attributes_for :working_hours, allow_destroy: false, reject_if: :all_blank
end

2. 调整控制器代码

更新update方法逻辑

添加匹配已有记录、确保7天记录齐全的处理逻辑:

class Api::V1::Admin::BusinessHoursController < Api::BaseController 
  def update
    @organization.build_business_hours unless @organization.business_hours
    @business_hour = @organization.business_hours

    # 为传入的working_hour匹配已有记录ID,实现更新而非重复创建
    process_working_hours_attributes

    if @business_hour.update(business_hour_params)
      # 确保周一到周日的working_hour记录全部存在
      ensure_all_working_days_exist
      render status: :ok,
        json: { notice: I18n.t("resource.update", resource_name: "Organization") }
    else
      # 返回所有验证错误(包含business_hours和working_hours的错误)
      all_errors = @business_hour.errors.full_messages + 
                   @business_hour.working_hours.flat_map(&:errors).flat_map(&:full_messages)
      render status: :unprocessable_entity, json: { errors: all_errors }
    end
  end

  private

    def business_hour_params
      params.require(:business_hours).permit(
        :enabled, :away_message, 
        # 新增允许:id参数,用于匹配已有记录
        working_hours_attributes: [:id, :day, :start_time, :end_time]
      )
    end

    # 为传入的working_hour属性匹配对应day的已有记录ID
    def process_working_hours_attributes
      return unless params.dig(:business_hours, :working_hours_attributes)

      params[:business_hours][:working_hours_attributes].each do |wh_attrs|
        next unless wh_attrs[:day].present?

        existing_wh = @business_hour.working_hours.find_by(day: wh_attrs[:day])
        wh_attrs[:id] = existing_wh.id if existing_wh.present?
      end
    end

    # 补充缺失的工作日记录(默认时间可根据业务需求调整)
    def ensure_all_working_days_exist
      all_days = %w(mon tue wed thu fri sat sun)
      existing_days = @business_hour.working_hours.pluck(:day)

      (all_days - existing_days).each do |day|
        @business_hour.working_hours.create!(
          day: day, 
          start_time: nil, # 可替换为业务默认开始时间
          end_time: nil    # 可替换为业务默认结束时间
        )
      end
    end
end

逻辑说明

  • 匹配已有记录:process_working_hours_attributes会为每个传入的工作日属性,匹配对应day的已有记录ID,Rails会自动根据ID执行更新操作,而非创建重复记录。
  • 确保7天记录齐全:ensure_all_working_days_exist会检查当前business_hour的工作日记录,自动补充缺失的日期记录。
  • 错误处理优化:合并返回business_hours和working_hours的所有验证错误,便于前端定位问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 22:45:15