Rails - 现有模型的最佳数据库设计

时间:2015-08-06 19:52:00

标签: ruby-on-rails

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

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

在此项目表中,有以下列:

role1_start_date, role2_start_date, role3_start_date, role4_start_date

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

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

我想我可以:

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

  2. 创建名为mpb_suspensions的表格,其中有两列:mpb_item_idrole_name。由于角色本身没有ID,因此role_name列将存储“role1”或“role2”等,具体取决于暂停的角色。

  3. 在我的View中,我需要能够“暂停”每项工作或所有工作。我不确定模型代码如何做到这一点以及哪种方法最好。

1 个答案:

答案 0 :(得分:0)

如果我必须构建这个,假设您提供的最少信息,我首先选择您描述的选项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_createafter_destroy挂钩中维护。

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