我发现自己开始利用检查持久性来让我的模型“工作”。包含持久性检查似乎方便和正确。另一方面,它感觉有点阴暗,好像我过于谨慎或者以一种小的方式打破ORM抽象。
一个例子可能是:
class Shipment
include DataMapper:Resource
belongs_to :address, :required => false
def shippable?
valid? && persisted? && !address.nil? && address.valid? && address.persisted?
end
end
在这种情况下,我需要一种方法告诉我货物是否可以发货。当它有效,保存到数据库并保存地址时,这是真的。
另一个例子可能是在回调中使用它来确定是否需要进行某些事情(价格重新计算)。
这段代码安全无误吗?
答案 0 :(得分:2)
好吧,如果您真的有可能在没有确认持久性或从数据库重新加载的情况下执行装运,那么检查持久性似乎对我来说是绝对必要的。
但事实确实如此吗?你如何得到这个运输行动?我想到这里有两个工作流程:
您要发货的订单。你点击“运送这个狗屎!”并转到ShipmentsController#new
,输入您的数据。通过按“保存”,您的货件将被验证并保留(如果有效)。持久化成功后(我假设shipment.save
返回false
,如果没有),您可以直接继续您的运输行动(无论在那里需要做什么)。如果shipment.save
告诉您它没有保留,#new
视图将再次呈现,并且尚未执行发货。因此,这就是向导类工作流的概念,其中“门”只允许您在持久性成功的情况下执行发货。
货件的发货和发货完全解耦。让我们说一个人计划发货,另一个人执行它们。前者创建了一个新的,有效的,持久的货件。后者以易于计划的货物清单开头。此ShipmentsController#index
使用Shipment.all
直接从数据库加载货件。无需在persisted?
操作中检查ShipmentsController#perform
。
确定。让它变得更复杂:
假设现在我们处于方案2中,第一个人可以删除货物,而第二个人可以执行它。如果不考虑这种情况,天真的应用程序会在#perform
完成后再次保存货件,并设置发货日期。这意味着丢失了“删除”数据库异常。但是,你不会使用状态机吗?所以我们说有一些过渡计划 - >已删除和计划 - >运。如果第1个人将状态设置为已删除而第2个人正在执行装运,则状态机会抛出异常:“没有从已删除到shpped的过渡,亲爱的!”尝试更新状态时。
所以我无法真正构成一个明确检查持久性不是偏执狂的场景。但是如果你有一个由于“不安全”工作流而真正发生的地方,你应该检查持久性。