我们正在建立一个简单的基于网络的系统,有人会添加一个记录,例如一个CMS页面,在网站上显示之前会得到负责人的批准。
如果作者随后决定稍后编辑该页面,我们希望根据实时副本创建草稿,经批准后,它将替换旧的实时页面。
我们考虑过进行完整的版本控制,但我们相信我们可以通过以下方式保持这种简单:只需一个草稿,2。只是一个现场,或者3.一个草稿和一个现场。
此功能需要跨多个“事物”而不仅仅是页面。
最后一个问题:您认为将这两个记录存储在同一个表中会更好,还是镜像表会更好?
我想这可能取决于但我不喜欢有两个具有相同结构的表的理想。稍微慢一点的操作(因为我们必须在显示数据的时候一直查询草稿)是值得的吗?
答案 0 :(得分:8)
当状态发生变化时,从表到表移动东西是一个坏主意。
如果要向工作流添加其他状态,则必须添加更多表。
这只是状态变化 - 这就是关系数据库的优化。
一个表,多个状态是标准方法。
如果你发现事情变得非常缓慢 - 并且你可以证明基于状态的查询是整个原因 - 你可以求助于“物化视图”或类似的技术,其中状态改变(以及由此产生的移动)是由RDBMS处理。
每个州的表格是一个坏主意。
您无法轻松添加状态。您还必须添加表格,这会让您感到痛苦。此外,您必须使用新表名更新代码以反映新工作流。
如果状态只是一个列,则添加新状态是在代码中添加新值和新的if语句。状态更改只是更新,而不是“删除插入”。
数据永远存在,每当用户有一个聪明的想法时,工作流程就会出现。不要因为想要改变工作流程而惩罚他们。
您不能轻易拥有子状态。许多状态机实际上是多个嵌套的状态机。使用table-per-state添加子状态会创建更多具有更多规则的表。
如果某个状态只是一个列,则嵌套的子状态只是另一个在代码中带有新if语句的列。状态更改只是更新,而不是“删除插入”。
您不能轻易拥有并行状态机。很多时候有许多并行状态代码更改。有时会有手动工作流程(批准)和自动化蠕虫流程(归档,复制到数据仓库等)。对于每州状态和并行状态机,没有办法合理地实施它
如果每个州只是一个列,则并行状态机只是并行更新。
答案 1 :(得分:3)
没有。一个实体类型,一个表。
重新考虑的理由:
草稿记录的数量比实际记录多一千倍。
安全条件要求直接访问数据库的某些用户对GRANT / REVOKE级别的草稿或实时记录具有某些权限,但不能超过其他类型的记录。
要考虑的第二个设计是项目的一个表格和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