我已经研究了一个复杂的数据结构,我想知道是否有一个不同的模式,我应该使用。
我有四个相互依赖的模型,Shift
,Day
,Cluster
和Schedule
。
Cluster
有一个日期,和许多Schedules
.Day
有一个Cluster
是最近的Day
的日期(但不一定相同),和许多Shifts
。- 如果最近的
Cluster
有一个对应Shift
的Schedule
,那么Shifts
在Day
上是有效的。
在Day
和Cluster
之间没有关联,因为我希望能够通过简单地添加一个Cluster
来添加Clusters
日期之间的所有Days
的移位。
我在app/models中的关联缩写如下:
class Cluster < ApplicationRecord
has_many :schedules, dependent: :destroy
end
class Schedule < ApplicationRecord
belongs_to :cluster
end
class Day < ApplicationRecord
has_many :shifts
end
class Shift < ApplicationRecord
belongs_to :day
end
我知道完全消除Cluster
和Schedule
类并将Schedule
属性直接存储在Shift
对象上是最简单的,但是如果开始时间改变,或者添加了移位,我希望所有受影响的移位都能自动更新,而不必为受该更改影响的每次移位访问数据库。
class Day
def cluster
@cluster ||= Cluster.most_recent_to date
end
end
class Cluster
class << self
def most_recent_to date
find_by(date: date_most_recent_to(date))
end
def date_most_recent_to date
date_comparison { |x| x <= date }.first
end
def date_comparison &date_comp
all_dates.select(&date_comp)
end
def all_dates
all.pluck(:date).sort.reverse
end
end
end
当前的结构对我正在做的工作有效,但是由于类的相互依赖,它容易出错和损坏。
是否有更好的抽象来表示模型之间的变量关联?
由于您的数据结构正在将大量潜在冗余的数据压缩到更少的行中,因此您获得了快速修改数据的能力,以换取更困难的读取时间。如果没有合适的约束,您可能会得到无意义的数据,正如您可能发现的那样。然而,如果你像你提到的那样展开你的数据,并且只有一个包含时间表和班次的天数列表,你可能会得到更糟糕的不一致。
2的想法。首先,我建议在组合中添加更多约束。例如,有两个cluster或两个day具有相同的日期是没有意义的,对吗?因此,将validates_uniqueness_of :date
添加到这些模型(和/或唯一的DB约束)。您可能还能想到其他约束条件,但在不了解您的模式的情况下,我很难提供其他建议。
第二,通过date
属性将cluster动态地附加到Days上可以节省一点时间,但是这可能会给您带来更多的麻烦。考虑每天直接设置belongs_to :cluster
。为了弥补在修改时间表方面的不便,可以使用表单更新UI,以便快速将给定的Cluster应用于天数范围。
注:如果你不接受我的第二个建议,你可以通过在计算中依赖数据库来简化你的代码,避免将整个关系加载到内存中(all_dates
将在扩展时谋杀你的性能):
class Day
def cluster
@cluster ||= Cluster.where("date <= ?", date).order(date: :desc).first
end
end