56

我是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

我的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

在 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">]`  

并在控制台中使用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">  

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

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

里面有什么问题?我想在类别和产品之间建立关系,就像
一个类别有_许多产品和产品属于_一个类别。

4

6 回答 6

115

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

于 2013-07-26T10:32:17.407 回答
32

尝试使用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
于 2014-02-27T16:24:09.027 回答
21

刚刚在试图用这个type保留词找到我自己的问题的解决方案时偶然发现了这篇文章,所以也许这可以帮助其他人。

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

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

禁用性病

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

class MyModel < ActiveRecord::Base # 禁用 STI
self.inheritance_column = :_type_disabled end

我知道我们没有使用任何继承,所以我认为这样做对我来说很好,但我不知道它可能会产生什么其他影响。如果其他人对此有任何意见,我很想知道。

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

于 2014-12-15T13:41:14.687 回答
4

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

class YourSubclass < Category
end
于 2014-01-23T20:30:05.090 回答
4

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

于 2019-06-21T15:02:13.947 回答
4

如果你发现这个问题是因为你遇到了同样的错误,并且你实际上是在使用 Rails STI,但是因为你试图重命名继承的子类而得到错误,这可能是因为你在type列中有旧数据并且忘记更新它。那么这个 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
于 2017-10-12T14:44:53.183 回答