#53 suggestion
Josh H

Class Table Inheritance

Reported by Josh H | November 10th, 2007 @ 02:37 PM

As a cleaner alternative to Single Table Inheritance, we talked about implementing Class Table Inheritance in DM.

As an added benefit, this would make it very easy to do Model Translation à la Globalize. To really facilitate switching languages, we discussed adding a context block that would allow DM to automatically choose a sub-class of a given parent class based on the supplied context (e.g. locale).

database(:default, 'en-US') do
  products = Product.all
  products.first.name # => Meatballs

database(:default, 'es-ES') do
  products = Product.all
  products.first.name # => Albóndigas

Comments and changes to this ticket

  • Matthew W

    Matthew W November 16th, 2007 @ 11:50 AM

    I suggest that if/when class table inheritance is implemented, it's done in such a way that Modules which are used as Mixins in the class hierarchy may have their own table too.

    I haven't yet looked in detail at the DataMapper implementation, but this is how I'm currently doing it with an ActiveRecord plugin:

    A class method 'mixin_extra_columns_from_table' defined on DataMapper::Base, usable like so:

    module Publishable

    def self.included(klass)

    klass.send(:mixin_extra_columns_from_table, :table_name => 'publishables')


    def publish

    unless first_published_date

    self.first_published_date = Date.today



    ... etc ...


    class Content < DataMapper::Base

    include Publishable


    this can then be used for the actual inheritance too, if you define DataMapper::Base#inherited to call it in the right on the subclass.

  • Sam Smoot

    Sam Smoot November 16th, 2007 @ 12:34 PM

    • State changed from “new” to “open”


    I'm not sure I understand the intent behind this really. Mostly your last sentence there, but your ::included hook would work fine in DM to override table names. So the mechanics of what you're saying are pretty straight-forward at least.

  • Matthew W

    Matthew W November 16th, 2007 @ 12:43 PM

    Yep sorry that last bit wasn't clear.

    I was just saying, if the (class) table inheritance mechanism is designed to work for Module inclusion, then it'll be easy to extend it to work for Class inheritance too.

    Pretty straightforward as you say, at least hopefully.

    In my example, the Publishable module mixes in some extra columns to classes in which it's included, which are loaded from a separate publishables SQL table. This has a polymorphic foreign key to the main table for the implementing class.

    so eg

    create table publishables (

    publishable_type enum('Content', 'Image', ...) not null,

    publishable_id int not null,

    author_id int not null,

    first_published_at datetime


    (If you're only using the mixin within a single class hierarchy, ie all the classes it's mixed into have a common superclass - then the foreign key needn't be polymorphic - in this case the publishable_type could be dropped).

    Happy to pitch in if necessary on this feature, as it would be my main reason for moving from ActiveRecord. Just looking into the DataMapper source in more detail now :)

  • Timothy Bennett (lanaer)

    Timothy Bennett (lanaer) December 7th, 2007 @ 06:56 PM

    Incidentally, what about the half-baked STI implementation currently in the code base? Are we switching to pure CTI, or defaulting to one and allowing the user to use the other via an option…?

  • Sam Smoot

    Sam Smoot December 10th, 2007 @ 01:25 PM

    Timothy: Ouch. :-(

    Yeah, it was a bug. Should be fine now.

    BTW, Class-Table-Inheritance is when you have extra tables for each sub-class that contain only the extended attributes for those types.

    Just wanted to clear that up since it seemed like there was some confusion between Class-Table-Inheritance and Concrete-Table-Inheritance (where you also have multiple tables, but the sub-tables each have a full set of attributes defined). When I say "CTI", I'm referring to Class, not Concrete.

    Anyways, STI should be fine now. I wouldn't say there's a need to "switch" to CTI, but that it should become an option. Not sure if it makes sense for one or the other to be a default...

  • Sam Smoot

    Sam Smoot December 27th, 2007 @ 10:45 AM

    • Milestone cleared.

    Putting this further out for now. Would like to focus on actual bugs stomping for 0.3.0 first.

  • Dan Kubb (dkubb)
  • Sam Smoot

    Sam Smoot April 27th, 2008 @ 10:19 PM

    • State changed from “open” to “invalid”

    Closing this for now. Needs some real solid design work to really get started. Work that should probably happen on the Wiki instead I think if anyone is interested in pasting the history from here to there...

  • Alex Coles

    Alex Coles May 8th, 2008 @ 06:50 AM

    Can this ticket be kept open but set to the 1.x milestone instead? This would provide a tracking ticket for work in the wiki.

  • wildchild

    wildchild February 4th, 2010 @ 07:54 AM

    • Tag set to mixin, spec, suggestion

    Oh yes, that could be a killer feature.

  • Dan Kubb (dkubb)

    Dan Kubb (dkubb) February 4th, 2010 @ 01:35 PM

    • State changed from “invalid” to “suggestion”

    I'm going to mark this as a suggestion. It's probably not something we can do until after DM 1.0 is released though, since it would require alot of internal refactoring.

    I probably wouldn't want to tackle this until the query/adapter API is rewritten to use veritas (http://github.com/dkubb/veritas/) since it will probably make STI and CTI much simpler to implement.

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »