检查DataMapper(或其他ORM)模型是否持久化

问题描述 投票:2回答:1

我发现自己开始利用检查持久性来让我的模型“工作”。包含持久性检查似乎方便和正确。另一方面,它感觉有点阴暗,好像我过于谨慎或以一种小的方式打破ORM抽象。

一个例子可能是:

class Shipment
  include DataMapper:Resource

  belongs_to :address, :required => false

  def shippable?
    valid? && persisted? && !address.nil? && address.valid? && address.persisted?
  end
end

在这种情况下,我需要一个方法告诉我货物是否可以发货。当它有效,保存到数据库并保存地址时,这是真的。

另一个例子可能是在回调中使用它来确定是否需要发生某些事情(价格重新计算)。

这段代码安全无误吗?

ruby orm persistence datamapper
1个回答
2
投票

好吧,如果您真的有可能在没有确认持久性或从数据库重新加载的情况下执行装运,那么检查持久性似乎对我来说是绝对必要的。

但情况确实如此吗?你如何得到这个运输行动?我想到这里有两个工作流程:

  1. 您要发货的订单。你点击“运送这个狗屎!”并访问ShipmentsController#new,输入您的数据。通过按“保存”,您的货件将被验证并保留(如果有效)。在持续成功后(我假设shipment.save返回false,如果没有)你可以直接继续你的运输行动(无论那里需要做什么)。如果shipment.save告诉你它没有持续,那么#new视图会再次渲染,并且还没有执行运输。因此,这就是类似向导的工作流程的概念,其中“门”只允许您在持久性成功的情况下执行运输。
  2. 货物的装运和装运的创建完全脱钩。让我们说一个人计划发货,另一个人执行它们。前者创建了一个新的,有效的,持久的货件。后者以易于计划的货物清单开头。这个ShipmentsController#index使用Shipment.all直接从数据库加载货物。无需在persisted?动作中检查ShipmentsController#perform

好。让它变得更复杂:假设现在我们处于方案2中,第一个人可以删除货物,而第二个人可以执行它。在没有考虑这种情况下,天真的应用程序将在#perform完成后再次保存货物,设置发货日期。这意味着丢失的“删除”数据库异常已经发生。但是,你不会使用状态机吗?因此,假设有计划的转换 - >已删除和计划 - >已发货。如果第2个人将状态设置为已删除而第2个人正在执行装运,则状态机会抛出异常:“没有从已删除到shpped的转换,亲爱的!”在尝试更新状态时。

所以我无法真正构建一个明确检查持久性不是偏执的场景。但是如果你有一个由于“不安全”工作流而真正发生的地方,你应该检查持久性。

© www.soinside.com 2019 - 2024. All rights reserved.