【问题标题】:Modeling relation between occurence and schedule for a gym class体育课的发生和时间表之间的建模关系
【发布时间】:2015-08-19 01:24:58
【问题描述】:

我正在尝试对课程的发生与其时间表之间的关系进行建模。这就是我所拥有的:

class Schedule < ActiveRecord::Base
  # Has attributes like 
  #  :starts_at (time only, no date)
  #  :repeats_on (weekday name represented as integer)
  #  :type (the type of exercise that will be taught, say Spin, Kickboxing)
  #  :duration
  has_many :occurrences
end  

class Teacher < ActiveRecord::Base
  has_many :occurrences
end

class Occurrence < ActiveRecord::Base
  belongs_to :teacher
  belongs_to :schedule
  # Has attribute
  #  :occurs_on (date only, no time, time comes from schedule reference)
end

现在,如果我对“时间表”进行更改(例如,我将周三 Spin 课程的 starts_at 从下午 4:30 更改为下午 5:00),这将影响所有过去发生的“属于到”这个“时间表”。为了避免这种情况,我似乎需要这样做:每当用户编辑“时间表”时,将旧时间表标记为非活动,然后创建一个新时间表。这样,只有新的事件会指向这个新的时间表,而过去的不会受到影响。

这是建立这种关系的正确方法吗?

【问题讨论】:

  • 您能否详细说明这将如何在应用程序中发挥作用?什么是用例场景?这将有助于我们了解数据的最佳结构方式。
  • 例如,我不明白发生的实际代表什么以及为什么当计划时间改变时,发生变得无效。
  • 每天,健身房都有许多课程,如旋转、普拉提等。这遵循每周的时间表或时间表。例如,周日下午 2:00 普拉提,下午 5:00 旋转,周一下午 5:00 有氧运动。现在,经理想为本月举行的课程分配教师。但是同一位老师并没有教授所有星期一下午 2:00 的课程。所以,我们需要区分日程类(没有日期信息,只有时间和工作日)和发生(有特定的日期和时间,还有其他属性,比如谁在教课)。
  • 现在,一个事件指向一个时间表。例如,8 月 19 日星期一下午 2 点事件引用了星期一下午 2 点的时间表。如果在 8 月 20 日,更改了星期一下午 2 点的时间表,以便开始时间变为下午 3 点,则它不应影响指向它的 8 月 19 日下午 2 点课程。它应该只影响未来的事件。这是因为我不想在事件中存储时间表的所有属性,如开始时间、课程类型、持续时间等(因为这将是重复的)。由于过去的事件都指向一个时间表,所以我在编辑时需要小心。
  • 好的,我明白了。我认为 MarsAtomic 有一个很好的答案,但我会给出另一个答案。

标签: ruby-on-rails associations rails-activerecord


【解决方案1】:

您需要将 Schedule 和 Occurrence 之间的关系反规范化一点,对 Schedule 的编辑不会影响未来的 Occurrence 实例。

现在,您的 Occurrence 从 Schedule 中获取其开始时间和结束时间,并且 Schedule 和 Occurrence 之间存在一对一的关系,因此更改 Schedule 会更改所有 Occurrence。

您应该将计划视为 Occurrence 的模板,并允许 Occurrence 维护自己的开始时间和结束时间字段。这两个实体可以具有相同的关系,但是当您查询开始时间时,您查询的是 Occurrence 而不是 Schedule。时间表仅用于提供“建议的”开始和结束时间。

非规范化意味着可以编辑 Schedule 而不影响旧的 Occurrences,并且可以单独编辑 Occurrences 而不会影响 Schedules 或其他 Occurrences。多做一点工作,您会获得更大的灵活性。

【讨论】:

  • 在每次出现时从计划对象中复制数据(例如开始时间、持续时间、类型以及未来可能的更多字段(例如位置、房间号、容量等))是否正确?此外,根据您建议的方法,一旦复制了相关数据,似乎就不需要发生事件和时间表之间的关系了。
  • 除非您希望 Schedule 和 Occurrence 以您当前拥有它们的方式紧密耦合,否则需要某种程度的非规范化来满足您的要求。您可以将它们完全解耦,但您可以通过保留它们之间的某种关系来保持一定的灵活性。考虑一种情况,您想要销毁给定计划生成的所有事件。如果没有关系,您必须创建一个长查询,以匹配 Schedule 和 Occurrence 之间的所有字段。通过关系,您可以简单地从 schedule_id = ? 的事件中删除
  • 存在一些耦合但仍然复制的问题是时间表可能已经完全改变(开始时间、课程类型、持续时间等)w.r.t。指向它的过去事件。因此,如果我尝试访问此新时间表的所有事件,我将获得更改此时间表之前的那些和之后的那些。由于无论如何我都必须做一些额外的工作,当用户尝试编辑它时,您如何看待创建一个新的计划对象?
  • 那你为什么还需要一个时间表呢?你有一堂课。它有一个发生。 1:1 对应。我不清楚维护单独的时间表对您有什么好处。一直以来,我都在想 Occurrence 描述类的对象......对不起。
  • 用户设置了每周计划,很少需要更改。这包含在调度表中,并由调度类建模。现在,在日历视图中,我们需要显示根据计划对象中指定的规则创建的实际事件。然后,这些事件将具有其他属性,例如不会出现在 Schedule 类中的教师和学生。用户不能每次都创建这些类。他们只是指定规则。但他们可以不时更改规则。是1:many对应。
【解决方案2】:

也许您应该有 3 个课程(课程、时间表和课程发生),而不仅仅是时间表和发生。

class Lesson < ActiveRecord::Base
  # Has attributes like
  #  :type (the type of exercise that will be taught, say Spin, Kickboxing)
  has_many :schedules
end

class Schedule < ActiveRecord::Base
  # Has attributes like
  #  :starts_at (time)
  #  :occurs_on (weekday name represented as integer)
  #  :duration
  belongs_to :lesson
  belongs_to :location
end

class LessonOccurrence < ActiveRecord::Base
  # Has attributes like
  #  :date
  #  :start_time
  #  :duration
  belongs_to :lesson
  belongs_to :teacher
  belongs_to :location
end

class Teacher < ActiveRecord::Base
  has_many :lesson_occurrences
end

因此,“跆拳道”类型的课程可能会在一周内发生 3 次,因此它具有三个计划对象。然后,当使用 course_occurrences 创建一周的时间表时,会向该课程添加 3 个 course_occurrence 对象,每个对象从 3 个 schedule 对象中的每一个中获取其时间和持续时间。

在您的情况下,我看不出任何避免时间和持续时间重复的方法,但我认为就像 MarsAtomic 建议的那样,您应该考虑不同类型的事情 - 时间表包含建议的时间和持续时间,而课程发生包含实际的时间和持续时间.

现在我想一想,这个答案本质上与 MarsAtomic 的答案相同 - 因为根据应用程序的其余部分,将日程表拆分为课程和日程表,您可能不会获得太多收益。

【讨论】:

  • 如果我已经在每个事件中存储了日期、开始时间、持续时间,我也可以存储课程,并且我不再需要事件、时间表和课程之间的任何关联。这是我对 MarsAtomic 解决方案的担忧。您如何看待我在问题中建议的解决方案?这确实避免了数据重复。
  • 你可以那样做,但我不喜欢。您基本上会说调度对象是不可变的,除了它们是否处于活动状态。它们不可变的原因不是反映了它所建模的现实,而仅仅是因为底层事物的结构方式。这让我感到不舒服,但这并不意味着它不会起作用或会导致问题。
  • 我只是将其扩展到包括位置,这可能是另一个具有房间号和容量等的课程。我会从 schedule 和 course_occurrence 中引用它。这看起来像是更多的重复,但我仍然认为这是要走的路,因为您已经区分了建议事物的模板和实际事物本身。
  • 也许是因为我称它为时间表,而假设时间表是不可变的似乎是错误的,因为时间表一直在变化。如果我将其称为 KlassTemplate,它会更有意义吗?模板是一成不变的。每次出现都是由模板生成的。我们不想更改此模板。我们只是创建与现有模板相似的新模板并停用旧模板。
  • 但是你打算用它来构建时间表吗?
猜你喜欢
  • 2020-06-24
  • 2018-07-03
  • 2019-07-11
  • 1970-01-01
  • 2013-03-27
  • 1970-01-01
  • 2019-03-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多