89

I want to use a column called type without invoking Single Table Inheritance (STI) - I just want type to be a normal column that holds a String.

How can I do this without having Rails expecting me to have single table inheritance and throwing an exception of The single-table inheritance mechanism failed to locate the subclass...This error is raised because the column 'type' is reserved for storing the class in case of inheritance.?

Any ideas on how to do this?

Joshua Pinter
  • 45,245
  • 23
  • 243
  • 245
Kvass
  • 8,294
  • 12
  • 65
  • 108

5 Answers5

144

In Rails 3.1 set_inheritance_column is deprecated, also you can just use nil as a name, like this:

class Pancakes < ActiveRecord::Base
    self.inheritance_column = nil
    #...
end
Valentin Nemcev
  • 4,940
  • 2
  • 20
  • 21
  • Actually, it appears as though that changed in `rails 3.2`. According to [apidock](http://apidock.com/rails/ActiveRecord/Base/inheritance_column/class): 'This method is deprecated or moved on the latest stable version. The last existing version (v3.1.0) is shown here.' Thanks for the tip though! – Batkins Oct 05 '12 at 19:54
  • It was deprecated in 3.1 and removed in 3.2, I think – Valentin Nemcev Oct 09 '12 at 11:38
  • 2
    @Batkins The `inheritance_column` reader is moved (hence "deprecated or moved" notice). The use of setting the `inheritance_column` instance variable directly is intended and is not deprecated. – lulalala Apr 22 '13 at 09:50
  • Worked in rails 5.1 – John Bachir Jun 22 '17 at 01:23
24

You can override the STI column name using set_inheritance_column:

class Pancakes < ActiveRecord::Base
    set_inheritance_column 'something_you_will_not_use'
    #...
end

So pick some column name that you won't use for anything and feed that to set_inheritance_column.


In newer versions of Rails you'd set inheritance_column to nil:

class Pancakes < ActiveRecord::Base
    self.inheritance_column = nil
    #...
end
mu is too short
  • 426,620
  • 70
  • 833
  • 800
  • 2
    do i need to actually create said column in my database? – Kvass Aug 21 '11 at 01:25
  • Thank you, this worked. A framework should NEVER!!!!! EVER!!!! dictate what a table field can't be named. That's supper bad for legacy data sets. – Jon Mar 10 '12 at 03:11
  • 5
    @Jon: Rails doesn't really care about legacy data or playing nice with others, Rails has too much attitude for that. You can make it behave itself with some effort but you always end up fighting a bit if you need to do something that Rails hasn't planned for (which unfortunately includes a lot of basic database concepts). OTOH, I'm a professional heretic so other Rails people will certainly be upset with me for pointing out the ideological problems :) – mu is too short Mar 10 '12 at 03:41
  • 10
    I think the idea is that Rails/Ruby prefer convention over configuration, so they try to optimize it for the use cases that they feel are correct. – Ibrahim May 23 '12 at 00:08
22

I know this question is rather old and this deviates a bit from the question you are asking, but what I always do whenever I feel the urge to name a column type or something_type is I search for a synonym of type and use that instead:

Here are a couple alternatives: kind, sort, variety, category, set, genre, species, order etc.

rii
  • 1,578
  • 1
  • 17
  • 22
11

Rails 4.x

I encountered the problem in a Rails 4 app, but in Rails 4 the set_inheritance_column method does not exist at all so you can't use it.

The solution that worked for me was to disable the single table inheritance by overriding ActiveRecord’s inheritance_column method, like this:

class MyModel < ActiveRecord::Base

  private

  def self.inheritance_column
    nil
  end

end

Hope it helps!

Itay Grudev
  • 7,055
  • 4
  • 54
  • 86
  • 11
    Simpler version: `class MyModel < ActiveRecord::Base` `self.inheritance_column = nil` `end`. Reference: http://apidock.com/rails/ActiveRecord/ModelSchema/ClassMethods/inheritance_column – Benjamin Bouchet Jun 23 '15 at 07:06
  • 1
    Works for me in rails 4.2.2. Perhaps you did not restart the server or spring after doing the change? – Benjamin Bouchet Jun 24 '15 at 07:21
  • 1
    And other users might find useful the simpler version I commented. As for the reload issue, I'm not expert but it would make sense to me to have a class property not automatically reloaded without unloading and reloading the class definition. – Benjamin Bouchet Jun 24 '15 at 11:49
  • 2
    I don't understand your reaction, I'm just trying to give a useful addition to your answer. Why are you feeling offended? I come in peace – Benjamin Bouchet Jun 26 '15 at 02:24
  • 2
    @Benj Looks like they deleted whatever comment(s) you're referring to so now it just looks like you're arguing with yourself. ;) – Joshua Pinter Feb 25 '18 at 21:06
1

If you want to do this for all models, you can stick this in an initializer.

ActiveSupport.on_load(:active_record) do
  class ::ActiveRecord::Base
    # disable STI to allow columns named "type"
    self.inheritance_column = :_type_disabled
  end
end
Bill Lipa
  • 2,039
  • 1
  • 19
  • 11