草稿记录应保存在单独的表格中吗?

时间:2010-03-11 16:09:26

标签: ruby-on-rails database-design web-applications application-design

我们正在建立一个简单的基于网络的系统,有人会添加一个记录,例如一个CMS页面,在网站上显示之前会得到负责人的批准。

如果作者随后决定稍后编辑该页面,我们希望根据实时副本创建草稿,经批准后,它将替换旧的实时页面。

我们考虑过进行完整的版本控制,但我们相信我们可以通过以下方式保持这种简单:只需一个草稿,2。只是一个现场,或者3.一个草稿和一个现场。

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

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

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

4 个答案:

答案 0 :(得分:8)

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

如果要向工作流添加其他状态,则必须添加更多表。

这只是状态变化 - 这就是关系数据库的优化。

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

如果你发现事情变得非常缓慢 - 并且你可以证明基于状态的查询是整个原因 - 你可以求助于“物化视图”或类似的技术,其中状态改变(以及由此产生的移动)是由RDBMS处理。

每个州的表格是一个坏主意。

  1. 您无法轻松添加状态。您还必须添加表格,这会让您感到痛苦。此外,您必须使用新表名更新代码以反映新工作流。

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

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

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

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

  3. 您不能轻易拥有并行状态机。很多时候有许多并行状态代码更改。有时会有手动工作流程(批准)和自动化蠕虫流程(归档,复制到数据仓库等)。对于每州状态和并行状态机,没有办法合理地实施它

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

答案 1 :(得分:3)

没有。一个实体类型,一个表。

重新考虑的理由:

  1. 草稿记录的数量比实际记录多一千倍。

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

  3. 要考虑的第二个设计是项目的一个表格和LiveItems的第二个表格。第二个表仅包含实时项目的ID。这样你就可以维护单表设计,但是你可以通过将单列表连接到主表来找到LiveItem。

答案 2 :(得分:2)

同意上述所有评论:只有一张表 使用scopes,您只需轻松获取已发布的帖子或草稿。

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

你有两种模式:

class Post < ActiveRecord::Base
end

class Draft < Post
end

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

每当你想要发布帖子时,你就必须这样做:

@draft = Draft.first
@draft[:type] = 'Post'

答案 3 :(得分:0)

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