Dry Validation:如何将birthday参数传入achievement_date_appr_r宏?
问题:校验
date_appr_r不早于出生日期的合约实现 输入JSON示例
{ "person": { "birthday": "1990-10-10" }, "achievement": { "date_appr_r": "2022-05-21" } }
当前合约代码
class CreateContract < BaseContract json do required(:person).hash do required(:birthday).value(:date) end required(:achievement).hash do required(:date_appr_r).value(:date) end end rule(person: :birthday).validate(:person_birthday) rule(achievement: :date_appr_r).validate(:achievement_date_appr_r) end
需求
需要校验date_appr_r不能早于birthday,请问如何将birthday参数传入achievement_date_appr_r宏?
解决方案
方案1:直接在关联字段的rule中编写校验逻辑
不需要单独依赖宏,直接在rule中同时指定两个关联字段,然后对比值:
class CreateContract < BaseContract json do required(:person).hash do required(:birthday).value(:date) end required(:achievement).hash do required(:date_appr_r).value(:date) end end rule(person: :birthday).validate(:person_birthday) # 关联两个字段,触发校验时同时获取两个值 rule(achievement: :date_appr_r, person: :birthday) do |date_appr_r, birthday| date_appr_r.failure("不能早于出生日期") if date_appr_r < birthday end end
方案2:在自定义宏中通过values访问出生日期
如果要保留achievement_date_appr_r宏,可以在宏内部通过values对象获取已解析的birthday值,同时修改rule关联两个字段确保birthday已完成校验:
class CreateContract < BaseContract json do required(:person).hash do required(:birthday).value(:date) end required(:achievement).hash do required(:date_appr_r).value(:date) end end rule(person: :birthday).validate(:person_birthday) # 关联两个字段,确保birthday已通过校验 rule(achievement: :date_appr_r, person: :birthday).validate(:achievement_date_appr_r) private def achievement_date_appr_r(value) # 从values中获取已解析的出生日期 birthday = values[:person][:birthday] return if value >= birthday key.failure("不能早于出生日期") end end
说明
- Dry-Validation中,
values对象存储了所有已通过前置校验的字段值,因此可以直接访问values[:person][:birthday]获取有效的日期对象。 - rule中同时指定多个字段时,只要其中任意字段的值发生变化,都会触发该rule的校验逻辑,确保两个字段的对比是实时的。
内容的提问来源于stack exchange,提问作者Андрей Нишанов
相关产品推荐
相关产品推荐

