1
votes

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?
2
(Haven't tried this.) What about creating a new base model that sets the table name?Dave Newton
@DaveNewton not sure I follow :\alf
Create a class to use as the base class. That class will set its table name using set_table_name. A and B will extend this new base class. I don't know if it'll work, it's just what I thought of.Dave Newton
@DaveNewton sounds nice! I didn't know about set_table_name. I'll try that and let you know. Thanks!alf
@DaveNewton it worked like a charm! Just a detail, set_table_name is deprecated. self.table_name= is the new thing. If you post this as an answer I'll accept it. Thanks again!alf

2 Answers

3
votes

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
0
votes

Try:

class A< ActiveRecord::Base
      self.abstract = false
end

Another approach:

I would create another model called C that would be self contained. It would include table that would have all of the attributes. And finally models A and B would have a polymorphic has_one relation to the C model.