Persistence of a model with arbitrary inheritance


#1

I want to write an application where plugins can add new model
objects, and I want these objects to be able to inherit from the basic
ones which will ship with the application.

I have identified a number of possible approaches for this:

  1. Use single table inheritance, and some kind of magic to add SQL
    columns which don’t exist on loading a new model defined in a plugin.
    Problem: if two models have fields with the same name and different
    types, I run into trouble (potential workaround is postfixing all
    field names with their type, and somehow magically mapping them back
    to the right ones in each class.)

  2. Use concrete table inheritance, and have the plugins define their
    own migrations somehow so that they can create their own tables.
    Problem: if I add a field in a base class, or if a plugin inherits
    from a model in another plugin and that plugin adds a field, then all
    subclasses need to have that field added.

  3. Store a map of :sym => (string or number or date) as multiple rows
    in a second table, with each row having a reference back to the owning
    object, a column saying which column the value is actually stored in,
    and then a column for each type I want to support. I’d probably have
    to have subclasses explicitly call a method which generates the
    getters and setters.

  4. Use some kind of native object mapping so that I don’t have to
    think about how to fit an object model onto an obsolete relational
    paradigm. So far I’ve investigated DyBase (the .so compiles but bombs
    out as soon as it’s loaded) and Madeleine (not liking it because
    everything that ever reads from or writes to the model needs to be
    implemented in a separate class, which makes everything much less
    transparent) and am looking for other options.

What are other people doing in this sort of situation? I imagine that
option #3 is the only feasible one which maintains the ability to use
Active Record for the storage, but I suspect that option #4 would be
the most transparent way to do it. Problem is I haven’t yet found a
decent ODBMS that works with Ruby.

TX