I have some questions on how to handle some inheritance I will need to do in a Rails app. I am implementing a process where users will be filling out multi-step forms - a.k.a. wizards - and need to handle several different types of wizard processes, with new ones cropping up each year and the old ones staying archived (in other words, there will be lots of wizard 'types' or flavors in existence).
>From a pure OO perspective, these wizards all share some common functionality, particularly a 'state' attribute which all wizards have to determine the current step that the user is on, and if they are finished or not. This state is managed internally within each different wizard type, controlled by a state machine which could work very differently between wizard types, however they all share the same 'completed' state at the end as a bare minimum. The basic class diagram I have in my head is of a base Wizard class at the top, with the basic shared 'state' attribute and some common methods there and the different types of wizards simply subclassing off of it. The first recommendation I saw for accomplishing inheritance in the ORM layer is using single table inheritance<http://martinfowler.com/eaaCatalog/singleTableInheritance.html>, however it quickly became clear to me that due to the differing columns/data that the subclasses will be storing now and into the future, it would be a very bad choice to try and wedge these all into a single "frankenstein" table. Next, I saw the alternative of concrete table inheritance<http://martinfowler.com/eaaCatalog/concreteTableInheritance.html>, which demonstrates only making the *subclasses* be tables (i.e. each subclass replicates the superclass data/behavior and can stand entirely on its own). I've started implementing this by using a combination of subclassing (for sharing methods/behavior) and a module mixin (for sharing the columns/data) - *gist here* <https://gist.github.com/2123152>. This is working fine for the most part so far, however it is a bit of work to pull up all wizard types that a user has in progress (i.e. the index action in wizards_controller), as the differing wizard types are completely disjoint, so to get them all in a collection I do something like this in the index action of my WizardsController: @wizards = Wizard.all_visible_subwizards.map(&:all).reduce(:union) but obviously this is a lossy conversion, since the wizard type can't be discerned from just the ID now. So, I was thinking it would be cool if the Wizard model could have at least a very basic table that all subclassed wizards inherit from, even if it is just PK and type, so that a subclassed wizard's type can be identified directly from its ID. Following this idea, using Wizard.get(id) could return the subclassed wizard type. Basically, I'm asking for the nice parts of STI, but across multiple tables. :-) Adding a Discriminator field triggers STI, which I don't want. A schema kind of like this would be ideal: Wizard: +----+------+--------------+ | id | type | state | +----+------+--------------+ | 1 | Foo | complete | | 2 | Bar | in-progress | | 3 | Bar | complete | +----+------+--------------+ FooWizard: +----+--------------------+ | id | other foo stuff... | +----+--------------------+ | 1 | ... | +----+--------------------+ BarWizard: +----+--------------------+ | id | other bar stuff... | +----+--------------------+ | 2 | ... | | 3 | ... | +----+--------------------+ I've seen this referred to as multiple table inheritance<http://en.wikibooks.org/wiki/Java_Persistence/Inheritance#Joined.2C_Multiple_Table_Inheritance> (of which there is an interesting article<http://mediumexposure.com/multiple-table-inheritance-active-record/>on mimicking it with AR using polymorphic associations), or as an interpretation of the ambiguous class table inheritance<http://martinfowler.com/eaaCatalog/classTableInheritance.html> pattern, the latter of which seems to have generated some DM-specific discussion<http://datamapper.lighthouseapp.com/projects/20609/tickets/53-class-table-inheritance>several years back. Has anyone done anything like this in DM before and could offer some suggestions? Or should I just stick with concrete table inheritance and put bandaids over the warts? Thanks! Abe -- You received this message because you are subscribed to the Google Groups "DataMapper" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/datamapper?hl=en.
