1

我有一个 Rails 应用程序,其中有一组模型(我们称之为它们Events),它们有一些共同的字段(、、、datetitleuser_id但是我需要一些“子类型”。ASalesEvent可能有一个article_id和一个amount。一个InterviewEvent可能有一个comments字段。等等。

我知道我需要满足 3 个业务要求:

  1. 在某些情况下,我会想将它们Events作为一个整体来构建(即“Events为该用户获取所有信息,并按时间顺序对它们进行排序,按月分组”)
  2. 在其他情况下,我只需要“子类型”(“获取该用户出售的所有文章”)。
  3. 子类型的数量可能适中(仍待定,但我们估计大约 20 个,具体取决于用户反馈)

我正在思考如何构建表格以支持此模型。我提出了 5 种可能的方法来对此进行建模,但每种方法都有其自身的缺点。

  • 选项 A:单独的表格-sales_eventsinterview_events. 这将使 2) 非常简单,并且 3) 可行,但是 1) 实施起来会非常麻烦。
  • 选项 B:单表继承。这将或多或少容易地解决 1) 和 2),但存在需要越来越多的可空字段的问题,这与 3) 不兼容
  • 选项 C:使用hstore- 因为我们在生产中使用 Postgres,我们可以使用hstore - 我们将有一个由“类型”字符串字段控制的“数据”字段。这将解决 1)、2) 和 3),但将我们与 postgresql 联系在一起,并且我们将使用我们不太熟悉的技术实现关键业务对象。如果可能的话,我宁愿避免这种情况。
  • 选项 D:带有多态链接的事件表***_event_data。我们基本上会有一个带有 type 和 event_data_id 的事件表,然后我们会有sale_event_data,interview_event_data等。这很好地满足了 1) 和 3),但是 2) 比其他方法有点弱,因为会有很多连接参与将事件与其数据联系起来。
  • 选项 E:销售has_one:事件。这与选项 D 的作用相同,只是“与其他人的链接”位于“数据”部分。也解决了1)和3),也涉及到了2)中的一些join,但是看起来更“干净”了一些;这里没有多态关联,只有“常规” sql 关联。

现在我倾向于使用选项 E。但我想知道是否有人认为它有明显的劣势,或者其他选项中的一个更大的好处,或者我没有想到的更好的选择。

4

2 回答 2

1

我已经使用了几乎所有你建议的选项。虽然出于以下原因我会消除选项 A、B 和 D,但我不能谈论 C,因为我不知道hstore也不使用 Postgres:

  • 选项 A:如您所说,单独的表将很难维护。每次您想要更改events的结构时,都必须在所有sub_events表上进行。
  • 选项B:单表继承,我用过很多,弃了。我觉得你在数据库中看到的和你的模型看起来之间存在很大的设计缺陷。也有很多 nil 字段。
  • 选项 D:带有指向 *_event_data 的多态链接的事件表。多态表不是为了这个目的。它们是一种type在模型中拥有不同字段的方法,因此您可以在不明确指定类型的情况下引用它。

选项 E 看起来不错,但是外键应该存储在哪里?很难说,并可能导致难以维护的情况。

就个人而言,我会使用我想编写的代码,什么会使使用它并在以后更容易阅读。我喜欢更具体的东西。我会简单地改变我命名模型的方式,以满足我的需求。你必须有创意!

我宁愿写这样的东西:

conference.event_information.users OR
sales_event.settings.title OR
interview.shared_information.comments OR
event.interview_details.starting_at

对于所有这些例子,我会使用经典has_manybelongs_to关系。

我认为数据类型和继承的整个概念会使您处于无法解决问题或使事情变得更清晰的情况。有时您只需要以不同的方式看待事物。

我希望它有所帮助。

于 2012-06-12T11:39:50.877 回答
0

默认情况下,Rails 不支持多表继承,但事实证明可以非常接近地对其进行建模。

见这篇文章:

http://mediumexposure.com/multiple-table-inheritance-active-record/

基本上,它使用一个模块来“修改”选项 D。我还在思考 Wawa Loo 的答案,但这一个也值得考虑。

编辑:关于多表继承的更多信息:一个名为“citier”的宝石http://peterhamilton.github.com/citier/index.html

EDIT2:我最终使用了multiple_table_inheritance:

https://github.com/mhuggins/multiple_table_inheritance

但我对结果不是很满意。这可能是让业务数据与持久性策略(如 ActiveRecord 所做的那样)紧密耦合并没有多大帮助的地方之一。它可以很好地完成这项工作,但并不完美(值得注意的是,实例方法可以“继承”,但不能“继承”类方法。范围之类的东西必须在每个子类上单独重复/混合)。

于 2012-06-12T14:35:02.720 回答