Ruby-on-rails ActiveRecord::SubclassNotFound:单表继承机制定位子类失败

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17879024/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 22:23:53  来源:igfitidea点击:

ActiveRecord::SubclassNotFound: The single-table inheritance mechanism failed to locate the subclass

ruby-on-railsinheritancerails-activerecord

提问by mrudult

I'm newbie to Rails.
I have two models Categoryand Productas follows:-

我是 Rails 的新手。
我有两个模型类别产品如下:-

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.rbis as follows:-

我的schema.rb如下:-

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.createcommand

在 Rails 控制台中,我使用Product.create命令 创建了两个产品和两个产品

[#<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.createcommand in console

并在控制台中使用Category.create命令 创建了两个类别

<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.allworks fine but Category.allgives

现在,Product.all工作正常,但Category.all给出

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.

ActiveRecord::SubclassNotFound: 单表继承机制无法定位子类:'clothing'。引发此错误是因为列“类型”保留用于在继承的情况下存储类。如果您不打算将此列用于存储继承类或覆盖 Category.inheritance_column 以使用另一列存储该信息,请重命名此列。

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.

里面有什么问题?我想在 Category 和 Product 之间建立一种关系,就像
一个类别 has_many products 和 products Beings_to 一个类别。

回答by Mike Szyndel

typeis restricted word, you can't use it as a column name in ActiveRecord models (unless you're doing STI).

type是受限制的词,您不能将其用作 ActiveRecord 模型中的列名(除非您正在执行 STI)。

回答by David West

Try using inheritance_column, then type will no longer be reserved:

尝试使用inheritance_column,然后类型将不再被保留:

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

回答by Topher

Just came across this post while trying to find a solution to my own problem with this typereserve word so maybe this can help someone else.

刚刚在尝试使用这个type保留字找到我自己的问题的解决方案时遇到了这篇文章,所以也许这可以帮助其他人。

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.

更改列的名称对我来说不是一个简单的解决方案,因为我正在处理一个从 mongodb 迁移到活动记录的现有完整系统。

I found adding self.inheritance_column = :_type_disabledto the model with the offending column name fixed the error which I found here.

我发现self.inheritance_column = :_type_disabled使用有问题的列名称添加到模型中修复了我在此处找到的错误。

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

禁用 STI

我必须添加“self.inheritance_column”而不是简单的“inheritance_column”才能使其工作。代码示例

class MyModel < ActiveRecord::Base # 禁用 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.

如果您可以更改列名并避免这样做,那么我确信这是一个更好的解决方案。

回答by Magne

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 typecolumn and forgot to update it. Then this rake task might help:

如果你发现这个问题是因为你遇到了同样的错误,而你实际上正在使用 Rails STI,但是因为你试图重命名继承的子类而得到错误,这可能是因为你在type列中有旧数据而忘记更新它。那么这个 rake 任务可能会有所帮助:

update_category_type_column_with_new_subclass_names.rake

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

回答by s2t2

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.

如果有人真的试图取消 STI,请尝试添加一个从父级继承的新类,有问题的错误消息应该会消失。

class YourSubclass < Category
end

回答by yozzz

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

self.inheritance_column = :sti_disabled如果当前 AR 模型没有使用 STI,则可以在模型(或其他名称)中进行设置