Ruby-on-rails 单表继承以及在 Rails 中的使用位置

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/555668/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 20:58:52  来源:igfitidea点击:

Single table inheritance and where to use it in Rails

ruby-on-railsinheritance

提问by Rishav Rastogi

I am stuck in a weird Design problem,

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

I am working on a two type of profiles Models,

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

  • User profile (belongs to User)
  • others that are maintain in-site as "bots" (doesn't belong to anybody)
  • 用户个人资料(属于用户)
  • 其他在现场作为“机器人”维护的(不属于任何人)

The typical OO behaviour of these two types of Profiles is same but only the important attributes/properties are common ( the very important ones 5-6 in number), others properties like "interests etc"(almost 10-15 properties) are not there for bot profiles

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

The coder who worked on this earlier created separate models/Controllers for bot profiles / User profiles which creates a lot of redundancy everywhere and also as expected hard to maintain, write tests etc.I wanted to DRY this up, atleast to solve some/all of these redundancy problems.

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

Somebody suggested Single Table Inheritance as a solution

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

Somebody suggested Use Polymorphic Associations instead.

有人建议改用多态关联。

what is the better approach. When do we actually use STI?

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

My own thought was STI is used best when attributes are same for Models and they differ in behaviour.

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

Thoughts about what can I do?

想想我能做什么?

采纳答案by womble

Characterising STI as mostly useful when attributes are the same but behaviour differs is "about right", but possibly a little limiting. I like to use STI when there is, as the name suggests, a clear OO-style inheritance relationship, rather than the database-style relationship between objects of different types.

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

If there is common code between bots and users, I'd say STI sounds like a winner. If there's just some common attributes, it's probably less applicable but still worth having a go at.

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

I'm a pretty experimental person, so my recommendation is to give it a go. Branch your code and refactor the models into an STI relationship. See if it really does dry things up, or just swaps one set of headaches for some other problem.

我是一个很有实验性的人,所以我的建议是试一试。分支代码并将模型重构为 STI 关系。看看它是否真的让事情变干了,或者只是将一组令人头疼的问题换成了其他一些问题。

One thing I think you won't see much benefit from is drying up your controllers. In my experience, STI models don't often translate into similarly related controllers. But that would be something else to experiment with. Sometimes there's a win, sometimes there isn't.

我认为您不会从中受益的一件事是让您的控制器枯竭。根据我的经验,STI 模型通常不会转化为类似的相关控制器。但这将是另一回事。有时有胜利,有时没有。

回答by Alex Reisner

I've written an article on this very topic, including some tips for working with STI:

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

Single Table Inheritance in Rails

Rails 中的单表继承

In short: there needs to be a clear OO-style inheritance relationship among objects (as eloquently stated by womble), not just some shared data. If there isn't a natural and obvious class hierarchy, a STI design may become difficult to maintain as your application evolves.

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

Secondly, you should consider if it's important to have all the data in one table. With polymorphic associations, your database queries will become more complex, and probably slower. If you're planning on listing all the objects together on the site (eg, in a table) then STI may be the way to go.

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

Thirdly, make sure your child classes don't have too many unique attributes. With all the data in one table, you don't want a lot of non-global columns. Not only do these take up space (not a major concern), but they make the data structure confusing. If you do have "special" columns you should explain them explicitly in your code.

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

Lastly, if you do use STI, I strongly recommend using a single controller for all of your child models. The main function of a controller is to provide access to objects, and if the objects need to be accessed in very different ways, then STI may not have been the correct design choice to begin with.

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

Check out my article (link above) for some more useful tips.

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

回答by wuputah

I would probably use either STI or no special features at all. You might be able to call everything a Profile and you'd know if it was a "bot" if its user was nil. You could also store a "type" field without using STI.

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

Certain things would affect my decision to use STI:

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

  • Whether there is bot-specific logic
  • How many bots there are versus users profiles (small number of bots means STI is OK - lots of bots and I might store them somewhere else)
  • 是否有bot特定的逻辑
  • 与用户配置文件相比,有多少机器人(机器人数量少意味着 STI 可以 - 很多机器人,我可能会将它们存储在其他地方)

The reason to avoid STI is sometimes it can get in your way. For instance it can be fairly annoying to change an object from one type to another (a Bot to a Profile in this case). Sometimes a simple "type" field is better.

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

Its worth noting that you'll probably want a common base class if you use STI. So you may want Profile, BotProfile, and UserProfile. The names are up to you. :)

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

回答by Sarah Mei

One gotcha of Rails STI - most plugins (and so forth) don't support it fully. You will find yourself patching many of the common ones.

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