ActiveRecord::SubclassNotFound: The single-table inheritance mechanism failed to locate the subclass
Ruby on-RailsInheritanceRails ActiverecordRuby on-Rails Problem Overview
I'm newbie to Rails.
I have two models Category and Product as follows:-
class Category < ActiveRecord::Base
attr_accessible :type
has_many :products
end
class Product < ActiveRecord::Base
attr_accessible :category_id, :color, :price, :title
belongs_to :category
end
And my schema.rb is as follows:-
ActiveRecord::Schema.define(:version => 20130725220046) do
create_table "categories", :force => true do |t|
t.string "type"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "products", :force => true do |t|
t.integer "category_id"
t.decimal "price", :precision => 10, :scale => 0
t.string "title"
t.string "color"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
end
In Rails console I created two products with two products with the Product.create command
[#<Product id: 1, category_id: 1, price: 500, title: "shirt", color: "blue", `created_at: "2013-07-25 22:04:54", updated_at: "2013-07-25 22:04:54">, #<Product id: 2, category_id: 1, price: 600, title: "tees", color: "black", created_at: "2013-07-25 22:05:17", updated_at: "2013-07-25 22:05:17">]`
And created two Categories with the Category.create command in console
<Category id: 1, type: "clothing", created_at: "2013-07-25 22:03:54", updated_at: "2013-07-25 22:03:54"><Category id: 2, type: "footwear", created_at: "2013-07-25 22:04:02", updated_at: "2013-07-25 22:04:02">
Now, Product.all works fine but Category.all gives
> ActiveRecord::SubclassNotFound: The single-table inheritance mechanism failed to locate the subclass: 'clothing'. This error is raised because the column 'type' is reserved for storing the class in case of inheritance. Please rename this column if you didn't intend it to be used for storing the inheritance class or overwrite Category.inheritance_column to use another column for that information.
What's wrong in there? I want to make a relationship between Category and Product like
a category has_many products and products belongs_to a category.
Ruby on-Rails Solutions
Solution 1 - Ruby on-Rails
type
is restricted word, you can't use it as a column name in ActiveRecord models (unless you're doing STI).
Solution 2 - Ruby on-Rails
Try using inheritance_column, then type will no longer be reserved:
class Category < ActiveRecord::Base
self.inheritance_column = :foo
attr_accessible :type
has_many :products
end
class Product < ActiveRecord::Base
attr_accessible :category_id, :color, :price, :title
belongs_to :category
end
Solution 3 - Ruby on-Rails
Just came across this post while trying to find a solution to my own problem with this type
reserve word so maybe this can help someone else.
Changing the name of the column isn't an easy solution for me because I'm working on a existing complete system migrating to active record from mongodb.
I found adding self.inheritance_column = :_type_disabled
to the model with the offending column name fixed the error which I found here.
>
>
> Disable STI
>
> I had to add “self.inheritance_column” as opposed to simply
> “inheritance_column” to get this to work. Code example
>
> class MyModel < ActiveRecord::Base # disable STI
> self.inheritance_column = :_type_disabled end
I know that we're not using any inheritance so I think it's fine for me to do this but I don't know what other implications there could be because of it. If anyone else has any opinions on this I'd be interested to know.
If you can just change the column name and avoid doing this then that's a much better solution I'm sure.
Solution 4 - Ruby on-Rails
if anyone is actually trying to pull off STI, try adding a new class that inherits from the parent, and the error message in question should go away.
class YourSubclass < Category
end
Solution 5 - Ruby on-Rails
If you found this question because you encountered the same error, and you are actually using Rails STI, but got the error because you were trying to rename the inherited subclasses, it's probably because you have old data in the type
column and forgot to update it. Then this rake task might help:
update_category_type_column_with_new_subclass_names.rake
# This will be run when running `rake categories:update_type_column_with_new_subclass_names`
namespace :categories do
desc 'Run through the categories with values in the type column and rename those according to the new subclass names: CategorySubclass1 -> CategorySubclass1NewName, CategorySubclass2 -> CategorySubclass2NewName, and CategorySubclass3 -> CategorySubclass3NewName . Run this rake task without arguments.'
task update_type_column_with_new_subclass_names: :environment do
Category.inheritance_column = :_type_disabled # to avoid getting error when using the type column: "ActiveRecord::SubclassNotFound: The single-table inheritance mechanism failed to locate the subclass: 'CategorySubclass1'"
categories = Category.where("type <> '' AND type IS NOT NULL")
categories.each do |a|
begin
case a.type
when 'CategorySubclass1'
a.type = 'CategorySubclass1NewName'
a.save!
when 'CategorySubclass2'
a.type = 'CategorySubclass2NewName'
a.save!
when 'CategorySubclass3'
a.type = 'CategorySubclass3NewName'
a.save!
end
rescue StandardError => e
puts '---'
puts 'Error trying to set :type for category with :'
puts 'id and url: '
puts ' ' + a.id.to_s
puts ' ' + a.type
puts 'Error message: '
puts e.message
puts '---'
end
end
Category.inheritance_column = :type # switch on the Rails STI after you've made your updates to the DB columns
end
end
Solution 6 - Ruby on-Rails
You can set inside your model self.inheritance_column = :_sti_disabled
(or some other name) if you are not using STI for current AR model