Search code examples
rubyruby-on-rails-3sti

Rails STI (Single Table Inheritance) without an abstract class


Background

I have a rails 3 app that has a model named A with the correspondent table as. Now I need a new model B that works exactly like A but has some other associations and methods (besides those in A).

Problem

I decided to use STI (Single Table Inheritance). I know I could do something like A < BaseModel and B < BaseModel, but there's already a lot of code assuming a table named as and it would require too much work.

So I'm trying to do B < A, where A is not abstract. I added the type column to as. Now the model B works perfect, but the model A doesn't know anything about inheritance and completely ignores the type column, so when I do A.create! it says that the column type cannot be empty. Also A.all returns B rows too.

What I've tried

  • Using the default value A for the type column. this works but only solves a part of the problem
  • Using a default scope in the A model. the problem with this approach is that it filters out all B rows for both models

Questions

  • How can I accomplish B < A in rails, where none of the models is abstract?
  • Are there any other nice alternatives?

Solution

  • The easiest solution might be to create a new base class and have both A and B extend it.

    The base class would set its table name to point to your current A table (as):

    class NewBaseClass < ActiveRecord::Base
      self.table_name = `as`
    end
    
    class A < NewBaseClass
      # ...
    end
    
    class B < NewBaseClass
      # ...
    end