【问题标题】:Rails - best database design for existing modelRails - 现有模型的最佳数据库设计
【发布时间】:2015-08-06 19:51:59
【问题描述】:

所以我继承了一些我需要添加到的 Rails 4 代码和数据库模型。

名为mpb_item 的模型有一个名为mpb_items 的表。

在这个项目表里面有如下列:

role1_start_date, role2_start_date, role3_start_date, role4_start_date

不理想,但就是这样。我猜他们应该在一个单独的角色表中。

我需要添加功能以暂停这些角色中的任何一个(或所有角色)。

我想我可以:

  1. 对于现有的表,我可以为每个现有的角色列添加一个新的布尔列。例如role1_suspended、role2_suspended 等

  2. 创建名为 mpb_suspensions 的表,包含 2 列:mpb_item_id 和 role_name。由于角色本身没有 id,因此 role_name 列将存储“role1”或“role2”等,具体取决于哪个角色被暂停。

在我的View 中,我需要能够“暂停”每项工作或所有工作。我不确定模型代码会如何执行此操作以及哪种方法最好。

【问题讨论】:

  • 您可以发布模型及其关联吗?你说的设计是什么意思?您需要带有 Rails 的 RDB(SQLite3、MySQL、PostgreSQL,最后一个是最强大的,具有大量数据)。当你说继承时,你的意思是你正在接受遗留代码或其他人的项目?
  • 有什么原因你不能创建合适的角色模型(哈哈)并在迁移中从mpb_item 表中迁移数据?
  • 别人的项目已经有一年左右的时间了。我不确定我们是否可以从 mpb_item 中提取数据,因为这样会为每个角色生成一个新行,这将如何工作?写'mpb_item.role.suspend'就好了,因为我刚刚在家,所以暂时无法发布代码...
  • 如果我们将角色拉到它自己的表中,那么在当前的 mpb_items 表中,mpb_items.id 将不再是唯一的,因为会有几行(由于 role_id)。目前每行只有一个 mpb_item。

标签: ruby-on-rails


【解决方案1】:

如果我必须构建这个,考虑到您提供的最少信息,我将从选择您描述的选项 2 开始。 (一个 RoleSuspension 是它自己的表)好处包括:

  • 新列总数减少,并且不会使任何表无限大
  • 没有多余的列(role1、role2 等)
  • 如果可能的角色数量发生变化,则无需添加更多列(即更加规范化)
  • 没有零值(方法 1)
  • 您可以轻松查询 RoleSuspensions 的整体状态(而使用方法 1,您需要计算 role1_suspended、role2_suspended 等中的非零值,然后将它们相加),并且更容易索引
  • 您可以将逻辑附加到 RoleSuspension;它是与其父 MbpItem 不同的动物。如果它只是一堆布尔列,那么任何复杂的逻辑都需要混入 MbpItem 模型中,并且维护起来可能会更加混乱。

按照选项 2 的逻辑,暂停角色将涉及创建如下新记录:

@mbp_item.role_suspensions.create!(role_number: 2)

检查暂停状态将涉及以下内容:

if @mbp_item.role_suspensions.any?
# or....
RoleSuspension.where(role_number: 3).each do |s|
  puts "Item #{s.mbp_item} is suspended for role #{s.role_number}."
end

使用这种方法,数据库性能将是一个更大的考虑因素,具体取决于对以下问题的回答:

  • 您需要在哪里以及多久检查一次角色暂停?
  • 当您检查角色暂停时,您是如何提出问题的?换句话说,是一些全局任务询问“存在哪些角色暂停,以及什么 mbp_items?”还是在渲染该对象时检查给定 mbp_item 的暂停?

如果您需要非常频繁地检查角色暂停,也许您应该向mbp_items 添加一个名为has_suspensions 的布尔列,这将是一个部分缓存,因为它将指示此 MbpItem 是否存在任何暂停(并且必须在 after_create 和 after_destroy 挂钩中维护)。

另一方面,如果您知道暂停信息永远不需要有自己的逻辑并且永远不需要直接查询,您可以添加一个单个 MbpItem 的列,role_suspensions,包含暂停角色的序列化整数数组。就数据库结构而言,这将是一种侵入性较小的方法,甚至可能比您的选项 1 更简单,因为它允许您以更少的代码和更少的元编程来挂起和取消挂起任何角色编号,但如果您需要为暂停或解除暂停过程添加任何奇特的逻辑(即,如果 RoleSuspension 值得作为自己的对象的状态),您会后悔这种方法。

【讨论】:

  • 很好的答案。我们将检查给定 MpbItem 的暂停情况,它不会很规律。当用户加载 MpbItem 时,在 View 屏幕上会显示每个角色以及它是否已暂停。在你的创造!代码,角色编号存储在哪里?我们目前不存储 id,可以使用常量吗?
  • 酷。如果它不是经常被检索的东西,我想新表方法在数据库性能方面会很好。
猜你喜欢
  • 2021-10-09
  • 1970-01-01
  • 2018-08-06
  • 2012-08-10
  • 2010-09-08
  • 1970-01-01
  • 1970-01-01
  • 2015-12-28
  • 1970-01-01
相关资源
最近更新 更多