你如何确保has_many总是“最小化”?

时间:2012-01-16 15:41:39

标签: ruby-on-rails

假设我正在编写代码来为公交车站建模。

每辆fleet总线至少有一个bus。我想弄清楚在模型中强制执行此最小数字的最佳方法。除非舰队本身被摧毁,否则舰队中的最后一辆公共汽车永远不会被毁坏。

一种方法是捕获bus对象上的关系。

class Bus
  ...
  before_destroy :check_minimum_busses_on_parent
end

然而,这普遍忽视了单一责任原则。公共汽车正在处理不是问题的车队问题。

我可以使用bus_observer方法创建before_destroy。现在所有的东西都是单一的责任,感觉就像我们有更多的物体在吵架而不是必要。

class BusObserver < ActiveRecord::Observer
  def before_destroy bus
    false if bus.fleet.busses.count <= 1
  end
end

这肯定会完成这项工作,但我对于它真正属于Fleet类的脱离并不是百分之百。

仍允许舰队摧毁其最后一班车

为了允许父fleet对象本身可能被销毁并想要摆脱它的最后一个总线,我也最终需要一些交叉通信,所以总线可以弄清楚是否舰队也得到了印章:

class BusObserver < ActiveRecord::Observer
  def before_destroy bus
    if  bus.fleet.busses.count <= 1 
      false unless bus.fleet.currently_being_destroyed?
    end
  end
end

这显然进入了纯粹丑陋的境界。可以将它包装到一个方法.bus_can_be_destroyed?中,该方法位于舰队对象上,但这并不是更好。

获得我所追求的目标的最简洁方法是什么?

2 个答案:

答案 0 :(得分:1)

你有一个Decommissioner类,给定一个总线,适当地处理业务逻辑?这似乎是明确和合理的。

如果您对记录退役事件感兴趣,它甚至可以是ActiveRecord模型。

有些事情:

class BusDecommissioner
  def initialize(bus)
    @bus = bus
  end
  def decommissionable?
    @bus.fleet.buses.size > 1
  end
  def decommission!
    @bus.destroy if decommissionable?
  end
end

答案 1 :(得分:1)

它适用于Association callbacks吗?根据文档,您可以使用before_remove回调并停止删除。