Single table inheritance and where to use them in Rails

I'm stuck in a weird design issue,

I am working on two types of profiles. Models

  • User Profile (owned by the User)
  • others that are supported locally as โ€œbotsโ€ (do not belong to anyone).

The typical OO behavior of these two types of profiles is the same, but only important attributes / properties are common (very important of them are 5-6), other properties, such as "interests, etc." (almost 10-15 properties) does not exist for bot profiles

The coder that worked on this earlier created separate models / controllers for bot profiles / user profiles that create a lot of redundancy everywhere, and as expected, it's hard to maintain, write tests, etc. I wanted to DRY this, at least solve some / all of these redundancy problems.

Someone suggested single-page inheritance as a solution

Someone suggested using polymorphic associations.

What a better approach. When do we really use STI?

My own thought was STI is best used when the attributes are the same for the models and they differ in behavior.

Thoughts on what I can do?

+52
inheritance ruby-on-rails
Feb 17 '09 at 6:02
source share
4 answers

Characterizing STIs is generally useful when the attributes are the same, but the differences in behavior are โ€œrightโ€, but perhaps a little limited. I like to use STI when there is, as the name implies, a clear OO style inheritance relationship, rather than a database type relationship between objects of different types.

If there is a common code between bots and users, I would say that STI sounds like a winner. If there are only some common attributes, this is probably less applicable, but still worth going for.

I am quite an experienced person, so my recommendation is to let him go. Separate your code and reformulate the models in relation to STI. See if it really drains, or just reduces one set of headaches to some other problem.

One thing, I think you will not see much benefit from drying your controllers. In my experience, STI models often go into similar controllers. But that would be something else to experiment with. Sometimes there is a victory, sometimes not.

+34
Feb 17 '09 at 6:26
source share
โ€” -

I wrote an article on this topic, including some tips for working with STI:

Inheriting individual tables in Rails

In short: there should be a clear relation of OO type inheritance between objects (as eloquently stated by womble), and not just some common data. If there is no natural and obvious class hierarchy, the STI design can become difficult to maintain as your application develops.

Secondly, you should consider whether it is important to have all the data in one table. With polymorphic associations, your database queries will be more complex and probably slower. If you plan to list all the objects together on a site (for example, in a table), then STI may be a way.

Third, make sure your child classes do not have too many unique attributes. With all the data in one table, you do not need many non-global columns. They occupy not only space (not much concern), but they create confusion in the data structure. If you have โ€œspecialโ€ columns, you should explicitly explain them in your code.

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

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

+29
Dec 11 '09 at 16:16
source share

I would probably use either STI or no special features at all. Perhaps you can name everything a profile, and you know if it was a โ€œbotโ€ if its user was zero. You can also save the type field without using the STI.

Some things will influence my decision to use STI:

  • Is there bot-specific logic
  • How many bots exist compared to user profiles (a small number of bots means that the STI is in order - there are many bots, and I could store them somewhere else).

The reason STI can be avoided can sometimes bother you. For example, it can be quite annoying to change an object from one type to another (in this case, Bot for the profile). Sometimes there is a simple type field.

It is worth noting that you will probably need a common base class if you use STI. Therefore, you might want Profile , BotProfile and UserProfile . The names are up to you. :)

+5
Feb 17 '09 at 6:37
source share

One of them is Rails STI - most plugins (etc.) do not fully support it. You will find that fixing many of the common ones.

+4
Feb 18 '09 at 0:23
source share



All Articles