Single Table Inheritance to Refer to a Child Class with Its Own Fields

Single Table Inheritance to refer to a child class with its own fields

The thing with single table inheritance is it is based on a single table model, not surprisingly, so you can't have different classes using different tables.

Typically the "Rails Way" is to bundle together all the possible fields that are required into a single table and use STI to handle the data mapping and validation issues for you. There are limits on what it can hide from the application, though, as generally a field being defined means it's usable by any of the classes bound to that table. Most people do not consider this to be an issue.

What you probably want to do is make a record that's joined in depending on the user type, for instance:

class User < ActiveRecord::Base
end

class AdminUser < User
belongs_to :admin_profile
end

class CommonUser < User
belongs_to :common_profile
end

This would require the users table having an admin_profile_id and common_profile_id column where the admin_profiles and common_profiles tables contain the required additional fields.

The attributes in these tables can be mapped back into the base class using the delegate method as required.

Moving the extra fields into a separate table may help compartmentalize things, but it also means reads will be slower because of the required join and the possibility of inconsistent records, due to one part being missing or out of date, is increased.

Generally you are okay loading all of the user-related fields into a single table even if many of these fields are not frequently used. The storage cost of a NULL field is typically low in the scheme of things and unless there are hundreds of these fields, the additional complexity exposed to the developer is minimal, a smaller price to pay than to have to create and reference records in pairs constantly.

How to make work single table inheritance and attr_accessible?

As discussed in the answer to Single Table Inheritance to refer to a child class with its own fields, ActiveRecord's implementation of Single Table Inheritance does not involve additional tables. All subclasses share the same table and rely on a type field to identify subclasses. That explains why your Provider instances only contain the fields available in your users table, including the type field that Rails adds for the subclassing support. Your providers table is unused.

Can model belong to STI child?

A better way to handle assocations and STI is to just setup the assocations to the base class:

class Place < ApplicationRecord
end

class SubPlace < Place
has_many :posts, foreign_key: 'place_id', inverse_of: 'place'
end

class AnotherKindOfPlace < Place
has_many :posts, foreign_key: 'place_id', inverse_of: 'place'
end

class Post < ApplicationRecord
belongs_to :place
end

This keeps things nice and simple since Post does not know or care that there are different kinds of places. When you access @post.place ActiveRecord reads the places.type column and will instanciate the correct subtype.

If the base Post class also has the association you just write it as:

class Place < ApplicationRecord
has_many :posts, foreign_key: 'place_id', inverse_of: 'place'
end

Single Table Inheritance in Django

There are currently two forms of inheritance in Django - MTI (model table inheritance) and ABC (abstract base classes).

I wrote a tutorial on what's going on under the hood.

You can also reference the official docs on model inheritance.

Doctrine table class inheritance when one subclass has no extra attributes

You are using joined inheritance model (class table inheritance), which uses a separate table for parent and each child. If you don't specify any fields in the child class, Doctrine will just create a table only containing ID field.

And a parent class can only use one type of inheritance, either class table inheritance or single table inheritance.

In that case, if you don't want to have a table with only id column in it, you need to change your data model.

Create Django abstract child model refering to the table of the parent model

OK, I finally found a solution my own answer: using Django proxy models to achieve single-table inheritance:

class Child(Parent):

def my_method(self):
return 'done'

class Meta:
proxy= True

very good answer on how to expand single-table inheritance to have child models identified as "distinct" of the Parent model, and between them: https://stackoverflow.com/a/60894618/12505071



Related Topics



Leave a reply



Submit