Подтвердить что ты не робот

ActiveRecord:: SubclassNotFound: механизм наследования с одной таблицей не смог найти подкласс

Я новичок в 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: механизм наследования с одной таблицей не смог найти подкласс: "одежда". Эта ошибка возникает из-за того, что тип столбца зарезервирован для хранения класса в случае наследования. Переименуйте этот столбец, если вы не собираетесь использовать его для хранения класса наследования или перезаписать Category.inheritance_column, чтобы использовать другой столбец для этой информации.

Что там плохого? Я хочу установить отношения между категорией и продуктом, например, категория has_many продуктов и продуктов принадлежит к категории.

4b9b3361

Ответ 1

type - это ограниченное слово, вы не можете использовать его как имя столбца в моделях ActiveRecord (если вы не делаете STI).

Ответ 2

Попробуйте использовать 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

Ответ 3

Просто наткнулся на этот пост, пытаясь найти решение моей собственной проблемы с этим type резервного слова, так что, возможно, это может помочь кому-то еще.

Изменение названия столбца не является для меня простым решением, потому что я работаю над существующей полной системой, переходящей на активную запись из mongodb.

Я обнаружил, что добавление self.inheritance_column = :_type_disabled к модели с ошибочным именем столбца исправило ошибку, которую я нашел здесь.

Отключить ИППП

Мне пришлось добавить "self.inheritance_column", а не просто "inheritance_column", чтобы заставить это работать. Пример кода

Класс MyModel <ActiveRecord :: Base # отключить STI
self.inheritance_column =: _type_disabled end

Я знаю, что мы не используем какое-либо наследование, поэтому я думаю, что это нормально для меня, но я не знаю, какие другие последствия могут быть из-за этого. Если у кого-то еще есть мнения по этому поводу, мне было бы интересно узнать.

Если вы можете просто изменить имя столбца и избежать этого, я уверен, что это гораздо лучшее решение.

Ответ 4

Если кто-то на самом деле пытается снять STI, попробуйте добавить новый класс, который наследуется от родителя, и соответствующее сообщение об ошибке должно исчезнуть.

class YourSubclass < Category
end

Ответ 5

Если вы обнаружили этот вопрос, потому что столкнулись с той же ошибкой, и на самом деле используете Rails STI, но получили ошибку, потому что вы пытались переименовать унаследованные подклассы, это, вероятно, потому, что у вас есть старые данные в столбце type и забыл обновить его. Тогда эта задача рейка может помочь:

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

Ответ 6

Вы можете установить внутри своей модели self.inheritance_column = :sti_disabled (или другое имя), если вы не используете STI для текущей модели AR