Abstract vs Polymorphic

I have an abstract class. Another developer wants to take the abstract
class and make it polymorphic.

1. Is this a good idea?
2. The abstract class and its descendents have controllers. Will the
controllers have to be changed?
3. How is an abstract class implemented in terms of migrations and the
database? Does the abstract class have a migration?

The idea is to minimize work.


I believe the word "abstract class" is used in other languages to describe what we in Ruby implement with a series of different patterns, including mixins (modules), interfaces, services, and contexts. I will admit that I rarely hear that term used in a Ruby context (because really "abstract classes" aren't native to Ruby, although you can use Ruby to implement objects that will behave the way you are thinking of an "abstract class" in another language).

It is difficult to answer your questions out of context, but generally speaking I personally feel that polymorphism is like a secret magic power that should be used only in rare circumstances. It may be appropriate for you -- but I've also seen many knee-jerk implementations of polymorphism that ultimately turned out to be cases where greater amounts of object encapsulation were more appropriate.

For example, let's say you had a database of users, and some of these users were also employees of the company. For employees, you need to record many, many additional points of data (job title, reports to, company division, etc). A Single Table Inheritance (STI) approach would add all the fields to the users table. A object oriented (encapsulated) approach would be to create a new table called Employees, and of course use a foreign key to link the User record to the corresponding Employee record.

If nearly all the records in the Users table were also Employees, STI might make sense. If 99% of the users were not employees (thus making all those fields blank on 99% of the records in the table) -- a more encapsulated data model might make more sense. (Of course there are other factors too).

On the other hand, maybe you would have reasons to implement different tables for Users and Employees, and in Ruby two different objects (User and Employee) could share functionality via a mixin. I would ask yourself these questions:

1) What's the most efficient way to encapsulate this data in the database?
2) What's the most efficient way to encapsulate this data in Ruby objects?
3) How can I create an interface that abstracts the implementation from the interface as cleanly as possible?

Generally speaking, if I wanted to share functionality between objects, I would start with a mix-in approach (using modules in Ruby). Wise old-timer programmers say things like "prefer composition over inheritance" (http://en.wikipedia.org/wiki/Composition_over_inheritance). In my experience, developers who "go for" Polymorphic approaches (and STI, which is a specific implementation of polymorphism in the context of a RDBSM back-end) tend to like Inheritance a lot, and while not ruling out STI for all situations, I look at it with a skeptical eye since I've seen it implemented when it wasn't necessary.

As far as question #2 - I can't really answer that without looking at your code.

As far as question #3 - as I said above, it's not immediately clear exactly the kind of Ruby implementation of "abstract class" you are referring to since AFAIK the idea of an abstract class is not native to Ruby. Migrations affect database tables, so if you are implementing your classes with an underlying database table, you will write a migration to affect the database table if it needs to be changed (or created, as the case may be), regardless of how the Ruby (/ActiveRecord) objects that read from/write to those database tables are defined.

Hope this helps!