Allow dynamic STI

I have a case when I want to use postgres table inheritance. I want my STI inheritance_column to be virtual. What is the reason to check for inheritance_column in the columns_hash?

https://github.com/rails/rails/blob/4-2-release_notes/activerecord/lib/active_record/inheritance.rb#L151

If we check only in the record (from the query result), then it would be possible to have STI based on virtual columns.

Regards!

I have a case when I want to use postgres table inheritance. I want my

STI inheritance_column to be virtual. What is the reason to check for inheritance_column in the columns_hash?

https://github.com/rails/rails/blob/4-2-release_notes/activerecord/lib/active_record/inheritance.rb#L151

If we check only in the record (from the query result), then it would be possible to have STI based on virtual columns.

Virtual in what sense?

AR assumes the type column exists in some queries. For example if you have

    Square < Polygon < AR::Base

then Square.count triggers

    SELECT COUNT(*) FROM "polygons" WHERE "polygons"."type" IN ('Square')

Can you make that work with your table definitions?

I have never used table inheritance in Postgres, but my understanding is that that kind of logic is builtin. I mean, if I understand it correctly

    SELECT COUNT(*) FROM "squares";

would count squares and all their descendants. You need to pass ONLY to opt-out.

My first impression (modulus, again, I have not used it) is that Postgres table inheritance is fundamentally incompatible with STI, and could maybe deserve its own plugin. I have seen

    GitHub - ninjudd/multi_table_inheritance: A Rails plugin that adds multi-table inheritance support using Postgres inheritance.

but does not seem to have much activity.

By virtual we mean that we don’t have the ‘type’ column in the DB at all. We determine it runtime via scope from the query.

Here is an example https://gist.github.com/gudata/7ff43e3b6600408b1c1e

multi_table_inheritance is very old and probably is not addressing the same problem.

By virtual we mean that we don't have the 'type' column in the DB at all.

We determine it runtime via scope from the query.

Here is an example Allow dynamic STI · GitHub

I don't quite see that in core.

AR does not have as a goal to support "inheritance" in a generic way. Rather, AR has STI baked in, where STI is a very concrete portable pattern:

    P of EAA: Single Table Inheritance

I believe trying to generalize the implementation of STI to fit other designs in would not be a good idea. The design of STI should model STI.

Rather, I see here a plugin that specifically models table inheritance as done in Postgres.

multi_table_inheritance

<Redirect Notice; is very old and probably is not addressing the same problem.

Yeah it's old and talks about Rails 2.3 in the README. I mentioned the plugin only because it might be relevant and a plugin author could perhaps check the implementation and see if they could copy some idea from it.

Doesn’t matter if the column comes statically or dynamically. The presence of the “type” virtual-column in the record should be enough.

record[inheritance_column].present?

instead of

record[inheritance_column].present? && columns_hash.include?(inheritance_column)

What do you think?

Doesn't matter if the column comes statically or dynamically. The presence

of the "type" virtual-column in the record should be enough.

record[inheritance_column].present?

instead of

record[inheritance_column].present? && columns_hash.include?( inheritance_column)

What do you think?

AR assumes the column exists. STI needs the column to perform certain queries related to the hierarchy as I showed before.

If AR cannot assume the column exists, then we need to introduce logic to account for that in those queries, and so on. The design deviates. There's no need for the design to deviate, AR models STI and STI has a type column.

I see your point that Rails is following the STI pattern.

However I can’t see why the column should be static in the schema and not to use the virtual one. I will have to spare some time to work on this to find out whats going to happen.

Thank you!

I see your point that Rails is following the STI pattern.

However I can't see why the column should be static in the schema and not to use the virtual one. I will have to spare some time to work on this to find out whats going to happen.

I would suggest a change of perspective, really.

Your application is not using a "dynamic STI". It is using Postgres true table inheritance. Everything is different, tables are different, attributes are different, queries are different.

In my view, it makes no sense to hack STI in AR to be able to support something that is not STI.

Instead of doing that, it would be better to implement support for Postgres table inheritance as is. The abstractions and API should reflect Postgres table inheritance.