【问题标题】:Single table inheritance and where to use it in Rails单表继承以及在 Rails 中的使用位置
【发布时间】:2010-10-08 00:38:35
【问题描述】:

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

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

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

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

早先从事此工作的编码人员为机器人配置文件/用户配置文件创建了单独的模型/控制器,这在任何地方都会产生大量冗余,并且正如预期的那样难以维护、编写测试等。我想把它干掉,至少可以解决部分/全部这些冗余问题。

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

有人建议改用多态关联。

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

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

想想我能做什么?

【问题讨论】:

    标签: ruby-on-rails inheritance


    【解决方案1】:

    我已经写了一篇关于这个主题的文章,包括一些使用 STI 的技巧:

    Single Table Inheritance in Rails

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

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

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

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

    查看我的文章(上面的链接)了解更多有用的提示。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 您在使用 STI 和 activeadmin 时遇到过任何问题吗?
      【解决方案3】:

      我可能会使用 STI 或根本不使用特殊功能。您可能可以将所有内容称为个人资料,并且如果其用户为零,您就会知道它是否是“机器人”。您也可以在不使用 STI 的情况下存储“类型”字段。

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

      • 是否存在特定于机器人的逻辑
      • 相对于用户配置文件有多少漫游器(漫游器数量少意味着 STI 正常 - 漫游器很多,我可能会将它们存储在其他地方)

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

      值得注意的是,如果您使用 STI,您可能需要一个通用的基类。所以你可能想要ProfileBotProfileUserProfile。名字由你决定。 :)

      【讨论】:

      • 我同意,正在考虑类似的方法。
      • 只是想知道,为什么将对象从一种类型更改为另一种很烦人? bot.becomes(Profile) 非常清晰易懂...
      • @andrew:我不知道#becomes,但这实际上并没有改变对象的类型,只是它的类名,实际上与STI无关。
      【解决方案4】:

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

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

      我是一个很有实验精神的人,所以我的建议是尝试一下。分支您的代码并将模型重构为 STI 关系。看看它是否真的把事情搞砸了,或者只是将一组令人头疼的问题换成了其他问题。

      我认为你不会从中看到太多好处的一件事是让你的控制器干涸。根据我的经验,STI 模型通常不会转化为类似的相关控制器。但这将是另一种尝试。有时会赢,有时不会。

      【讨论】:

      • 我想我会尝试 STI。但是,如果我只有几个共同属性,我可能会遇到什么问题?
      • 处理控制器的另一种方法是对它们进行子类化,就像模型一样...重构以使它们之间可以共享通用方法。
      • @Andrew:IME,除了在(相对罕见的)裸机脚手架 CRUD 情况下,它的工作几乎不如模型的子类化。
      • @rishavrastogi 如果有很多不同的属性,属性和动作的语义相同的机会就会减少。当然,如果你有明显的继承关系,这种风险就会大大降低。
      • 对于所有其他不同的属性,我非常成功地使用的一种技术是 STI+属性关联。您的各种 STI 模型可以定义自己的属性关联(has_one),并在 STI 模型中保留真正共享的属性
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-19
      • 1970-01-01
      • 2011-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多