8

我们正在构建一个简单的基于 Web 的系统,通过该系统,某人添加了一个记录,例如一个 CMS 页面,该记录在显示在网站上之前得到负责人的批准。

如果作者决定稍后编辑该页面,我们希望基于 Live Copy 创建一个草稿,经批准后它将替换旧的 Live 页面。

我们考虑过进行完整的版本控制,但相信我们可以通过 1. 一个草稿,2. 一个 live 或 3. 一个草稿和一个 live 来保持这个更简单。

此功能需要跨多个“事物”,而不仅仅是页面。

最后一个问题:您认为将这两条记录存储在同一张表中更好,还是镜像表更好?

我想这可能取决于,但我不喜欢拥有两个具有相同结构的表的理想状态。换取稍微慢一点的操作(因为我们在显示数据时必须一直查询草稿)值得吗?

4

4 回答 4

10

当状态发生变化时将东西从一个表移到另一个表是一个坏主意。

当您想向工作流添加其他状态时,您必须添加更多表。

这只是一种状态变化——这就是关系数据库的优化目标。

一张表,多种状态是标准方法。

如果你发现事情慢得可怕——并且你可以证明基于状态的查询是全部原因——你可以求助于“物化视图”或类似的技术,其中状态变化(以及由此产生的移动)由关系数据库管理系统。

每个状态表是一个坏主意。

  1. 您不能轻易添加状态。您还必须添加表格,这很痛苦。此外,您必须使用新的表名更新代码以反映新的工作流程。

    如果状态只是一列,那么添加新状态就是在代码中添加新值和新 if 语句。状态更改只是更新,而不是“删除插入”。

    数据永远存在,每当用户有一个聪明的想法时,工作流程就会来来去去。不要因为他们想要改变工作流程而惩罚他们。

  2. 您不能轻易拥有子状态。许多状态机实际上是多个嵌套的状态机。使用 table-per-state 添加子状态会创建更多具有更多规则的表。

    如果状态只是一列,则嵌套子状态只是代码中带有新 if 语句的另一列。状态更改只是更新,而不是“删除插入”。

  3. 您不能轻易拥有并行状态机。很多时候有很多并行的状态码变化。有时有手动工作流程(批准)和自动化工作流程(归档、复制到数据仓库等)。对于每个状态表和并行状态机,没有办法合理地实现它

    如果每个状态只是一列,则并行状态机只是并行更新。

于 2010-03-11T16:15:24.710 回答
5

不,一种实体类型,一张表。

重新考虑的原因:

  1. 草稿记录的数量比现场记录的数量高出数千比一。

  2. 安全条件要求直接访问数据库的某些用户在 GRANT/REVOKE 级别对草稿或实时记录具有某些权限,但对其他类型的记录没有权限。

要考虑的第二个设计是一个表用于 Items,第二个表用于 LiveItems。第二个表仅包含活动项目的 ID。这样,您就可以维护单表设计,但您可以通过将单列表连接回主表来找到 LiveItems。

于 2010-03-11T16:28:42.717 回答
2

同意上面给出的所有评论:只有一张桌子。
使用范围,您可以轻松地仅获取已发布的帖子或草稿。

我不会推荐它。
但是,如果您真的希望草稿和已发布条目有两种不同的模型,那么还有另一种解决方案:STI

你有两个模型:

class Post < ActiveRecord::Base
end

class Draft < Post
end

任何 Draft 对象都取自 Post 表。
Type 参数使其成为帖子或草稿。

每当您想发布帖子时,您都必须这样做:

@draft = Draft.first
@draft[:type] = 'Post'
于 2010-03-11T17:05:37.137 回答
0

我刚刚为这样的用例制作了一个宝石。它将草稿存储在一个单独的表中: https ://github.com/ledermann/drafting

于 2015-08-04T09:00:20.280 回答