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