如何实现租房应用Home模型布尔属性的Active Record更新规则?
批量处理布尔属性依赖规则的实现方案
针对50余组类似with_swimming_pool/with_swimming_pool_alarm的布尔属性对,我们可以通过抽象属性映射+通用回调/校验的方式统一实现规则,避免重复代码:
1. 定义属性依赖映射
首先把所有关联的属性对整理成哈希,方便后续批量处理:
# 在Homes模型中定义 ALARM_DEPENDENCIES = { with_swimming_pool: :with_swimming_pool_alarm, # 依次添加其他50+组属性,例如: with_garden: :with_garden_alarm, with_garage: :with_garage_alarm, # ...更多属性对 }.freeze
2. 实现自动赋值逻辑(规则2)
通过before_validation回调,批量处理“设置警报则自动启用主属性”的需求:
before_validation :sync_dependent_attributes def sync_dependent_attributes ALARM_DEPENDENCIES.each do |main_attr, alarm_attr| # 当警报属性为true时,强制主属性为true self[main_attr] = true if send("#{alarm_attr}?") end end
3. 添加合法性校验(规则1)
自定义校验方法,批量检查所有属性对是否违反“仅启用警报未启用主属性”的规则:
validate :alarm_dependency_validation def alarm_dependency_validation ALARM_DEPENDENCIES.each do |main_attr, alarm_attr| if send("#{alarm_attr}?") && !send("#{main_attr}?") errors.add(alarm_attr, "不能单独启用,请先启用#{main_attr.to_s.humanize}") end end end
4. 实现主属性置假时的重置逻辑(规则3)
通过before_update回调,批量处理“主属性置false则重置对应警报为nil”的需求:
before_update :reset_alarm_on_main_disable def reset_alarm_on_main_disable ALARM_DEPENDENCIES.each do |main_attr, alarm_attr| # 检查主属性是否被更新为false if changes.key?(main_attr) && changes[main_attr].last == false self[alarm_attr] = nil end end end
5. 复用测试用例
不用为每组属性写重复测试,通过RSpec的共享示例批量生成测试:
# 在spec/models/home_spec.rb中 shared_examples "alarm dependency rules" do |main_attr, alarm_attr| it "无效:仅启用#{alarm_attr}但未启用#{main_attr}" do home = build(:home, alarm_attr => true, main_attr => false) expect(home).to be_invalid end it "启用#{alarm_attr}时自动设#{main_attr}为true" do home = create(:home, alarm_attr => true) expect(home.send(main_attr)).to be_truthy end it "当#{main_attr}设为false时重置#{alarm_attr}为nil" do home = create(:home, main_attr => true, alarm_attr => true) home.update(main_attr => false) expect(home.send(alarm_attr)).to be_nil end end # 遍历所有属性对生成测试 Homes::ALARM_DEPENDENCIES.each do |main_attr, alarm_attr| include_examples "alarm dependency rules", main_attr, alarm_attr end
内容的提问来源于stack exchange,提问作者Quentin Gaultier
相关产品推荐
相关产品推荐

