如何验证整数区间不被另一个整数区间包含?附周期验证场景
解决周期包含的验证规则问题
我来帮你搞定这个周期验证的问题!你想要实现的是:确保新创建(或更新)的周期既不被已有周期完全包含,也不完全包含任何已有周期——就像你举的例子,已有25-30的情况下,新建20-40会触发错误,这个需求很明确。
先说说你现有代码里的两个小问题:
errors.add的写法不对:Rails的errors.add方法第一个参数是字段名,第二个是错误信息,你现在把多个参数堆进去会导致信息显示异常。- 未完成的
period_overlap方法还没覆盖到“完全包含”的两种核心场景,需要调整查询条件。
下面是完整的实现方案,直接就能用:
1. 编写验证方法
在你的模型里添加这个自定义验证方法:
def period_cannot_be_contained_or_contain_others # 查询所有和当前周期存在包含关系的已有周期(排除自身,避免更新时误判) conflicting_periods = self.class.where.not(id: id).where( '(start_week <= :current_start AND finish_week >= :current_finish) OR (:current_start <= start_week AND :current_finish >= finish_week)', current_start: start_week, current_finish: finish_week ) if conflicting_periods.any? errors.add(:base, "该周期不能包含已有周期,也不能被已有周期包含") end end
2. 启用验证
在模型里调用这个验证:
validate :period_cannot_be_contained_or_contain_others
逻辑说明
这个查询覆盖了两种需要拦截的场景:
- 已有周期包含当前周期:比如已有25-30,当前周期是26-29,这时候已有周期的start <= 当前start,且已有finish >= 当前finish
- 当前周期包含已有周期:比如已有25-30,当前周期是20-40,这时候当前start <= 已有start,且当前finish >= 已有finish
另外,where.not(id: id)是为了处理更新场景——当你修改一个已有周期时,不会把它自己当成冲突的周期。
小提示
如果你的start_week和finish_week是日期类型(而不是周数整数),这个逻辑完全通用,只需要保证字段名对应就行。
内容的提问来源于stack exchange,提问作者Tommy Tayler
相关产品推荐
相关产品推荐

