单表继承及其在Rails中的使用位置

我陷入了一个奇怪的设计问题,

我正在研究两种类型的配置文件模型,

  • 用户个人资料(属于用户)
  • 在现场以“机器人”身份维护的其他人(不属于任何人)

这两种类型的配置文件的典型OO行为是相同的,但只有重要的属性/属性是通用的(非常重要的属性/属性为5-6),其他属性(如“兴趣等”)(几乎10-15个属性)不存在 机器人档案

较早从事此工作的编码人员为bot配置文件/用户配置文件创建了单独的模型/控制器,从而在各处创建了很多冗余,并且由于难以维护,编写测试等原因,我想对此进行干燥,以解决部分/全部问题 这些冗余问题。

有人建议单表继承作为解决方案

有人建议改为使用多态关联。

有什么更好的方法。 我们什么时候真正使用STI?

我自己的想法是,当Model的属性相同且行为不同时,最好使用STI。

关于我该怎么办的想法?

Rishav Rastogi asked 2020-01-13T00:36:56Z
4个解决方案
35 votes

当属性相同但行为不同时,将STI表征为最有用的“大约正确”,但可能有一点限制。 顾名思义,我喜欢使用STI,但要使用明确的OO样式继承关系,而不要使用不同类型的对象之间的数据库样式关系。

如果机器人和用户之间存在通用代码,我想说STI听起来像是赢家。 如果只有一些共同的属性,它可能不太适用,但仍然值得一试。

我是一个非常有实验性的人,所以我的建议是尝试一下。 分支您的代码并将模型重构为STI关系。 看看它确实确实使事情干dry了,还是只是换了一些其他问题而令人头疼。

我认为您不会从中受益匪浅的一件事就是使控制器干drying。 以我的经验,STI模型通常不会转换成类似相关的控制器。 但这将是其他尝试。 有时有胜利,有时没有。

womble answered 2020-01-13T00:37:30Z
29 votes

我已经写了一篇有关该主题的文章,其中包括使用STI的一些技巧:

Rails中的单表继承

简而言之:对象之间需要有一个清晰的OO风格继承关系(正如womble雄辩地说的),而不仅仅是一些共享数据。 如果没有自然而明显的类层次结构,则随着应用程序的发展,STI设计可能会变得难以维护。

其次,您应该考虑将所有数据放在一个表中是否重要。 使用多态关联,您的数据库查询将变得更加复杂,并且可能会更慢。 如果您打算在站点上(例如,在表中)一起列出所有对象,那么STI可能是可行的方法。

第三,确保您的子类没有太多的唯一属性。 将所有数据都放在一个表中,您不需要大量非全局列。 这些不仅占用空间(不是主要问题),而且使数据结构混乱。 如果确实有“特殊”列,则应在代码中明确说明它们。

最后,如果您确实使用STI,我强烈建议您为所有子模型使用单个控制器。 控制器的主要功能是提供对对象的访问,如果需要以非常不同的方式访问对象,则STI可能不是开始时的正确设计选择。

查看我的文章(上面的链接)以获取更多有用的提示。

Alex Reisner answered 2020-01-13T00:38:18Z
5 votes

我可能会使用STI或根本不使用任何特殊功能。 您可能可以将所有内容称为配置文件,并且如果用户为nil,则知道它是否为“机器人”。 您也可以在不使用STI的情况下存储“类型”字段。

某些事情会影响我使用STI的决定:

  • 是否存在特定于机器人的逻辑
  • 相对于用户个人资料有多少个机器人(少量的机器人意味着STI可以-很多机器人,我可能将它们存储在其他位置)

避免性传播感染的原因有时可能会妨碍您。 例如,将一个对象从一种类型更改为另一种类型(在这种情况下是从Bot更改为Profile)可能会很烦人。 有时,简单的“类型”字段会更好。

值得注意的是,如果您使用STI,可能会需要一个通用的基类。 因此,您可能需要ProfileBotProfileUserProfile。名称由您决定。 :)

wuputah answered 2020-01-13T00:39:00Z
4 votes

Rails STI的一个陷阱-大多数插件(等等)并不完全支持它。 您会发现自己修补了许多常见的补丁。

Sarah Mei answered 2020-01-13T00:39:20Z
translate from https://stackoverflow.com:/questions/555668/single-table-inheritance-and-where-to-use-it-in-rails