Rails -- use type column without STI?
Asked Answered
P

5

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?

Prestidigitation answered 20/8, 2011 at 20:41 Comment(0)
C
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
Creamcolored answered 8/8, 2012 at 19:8 Comment(4)
Actually, it appears as though that changed in rails 3.2. According to apidock: '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!Singularity
It was deprecated in 3.1 and removed in 3.2, I thinkCreamcolored
@Singularity 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.Shushan
Worked in rails 5.1Ply
V
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
Viscous answered 20/8, 2011 at 20:53 Comment(4)
do i need to actually create said column in my database?Prestidigitation
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.Marder
@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 :)Viscous
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.Gift
R
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.

Rollandrollaway answered 5/2, 2016 at 20:14 Comment(0)
F
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!

Fleeting answered 16/4, 2015 at 1:42 Comment(5)
Simpler version: class MyModel < ActiveRecord::Base self.inheritance_column = nil end. Reference: apidock.com/rails/ActiveRecord/ModelSchema/ClassMethods/…Cucullate
Works for me in rails 4.2.2. Perhaps you did not restart the server or spring after doing the change?Cucullate
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.Cucullate
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 peaceCucullate
@Benj Looks like they deleted whatever comment(s) you're referring to so now it just looks like you're arguing with yourself. ;)Turboelectric
D
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
Disafforest answered 12/10, 2016 at 19:56 Comment(1)
Or better yet - in ApplicationRecord.Rattan

© 2022 - 2024 — McMap. All rights reserved.