web-dev-qa-db-fra.com

ActiveRecord :: SubclassNotFound: Le mécanisme d'héritage d'une table unique n'a pas pu localiser la sous-classe

Je suis novice chez Rails.
J'ai deux modèles Catégorie et Produit comme suit: -

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

Et mon schema.rb est le suivant: -

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

Dans la console Rails j'ai créé deux produits avec deux produits avec la commande 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">]`  

Et créé deux catégories avec la commande Category.create dans la 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">  

Maintenant, Product.all fonctionne bien mais Category.all donne

ActiveRecord :: SubclassNotFound: Le mécanisme d'héritage d'une table unique n'a pas pu localiser la sous-classe: "vêtements". Cette erreur est générée car la colonne 'type' est réservée au stockage de la classe en cas d'héritage. Veuillez renommer cette colonne si vous n'aviez pas l'intention de l'utiliser pour stocker la classe d'héritage ou remplacer Category.inheritance_column pour utiliser une autre colonne pour ces informations.

Qu'est-ce qui ne va pas là-dedans? Je veux faire une relation entre la catégorie et le produit comme
une catégorie a_de nombreux produits et produits appartient_ à une catégorie.

43
mrudult

type est Word restreint, vous ne pouvez pas l'utiliser comme nom de colonne dans les modèles ActiveRecord (sauf si vous faites STI).

94
Mike Szyndel

Essayez d'utiliser inheritance_column, puis le type ne sera plus réservé:

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
24
David West

Je suis juste tombé sur ce message en essayant de trouver une solution à mon propre problème avec ce type mot de réserve, donc cela peut peut-être aider quelqu'un d'autre.

Changer le nom de la colonne n'est pas une solution facile pour moi car je travaille sur un système complet existant migrant vers l'enregistrement actif à partir de mongodb.

J'ai trouvé l'ajout de self.inheritance_column = :_type_disabled au modèle avec le nom de colonne incriminé a corrigé l'erreur que j'ai trouvée ici .

Désactiver les IST

J'ai dû ajouter "self.inheritance_column" au lieu de simplement "inheritance_column" pour que cela fonctionne. Exemple de code

classe MyModel <ActiveRecord :: Base # disable STI
self.inheritance_column =: _type_disabled end

Je sais que nous n'utilisons aucun héritage, donc je pense que c'est bien pour moi de le faire, mais je ne sais pas quelles autres implications il pourrait y avoir à cause de cela. Si quelqu'un d'autre a des opinions à ce sujet, je serais intéressé de le savoir.

Si vous pouvez simplement changer le nom de la colonne et éviter de le faire, c'est une bien meilleure solution, j'en suis sûr.

13
Topher

si quelqu'un essaie réellement de supprimer STI, essayez d'ajouter une nouvelle classe qui hérite du parent, et le message d'erreur en question devrait disparaître.

class YourSubclass < Category
end
3
s2t2

Si vous avez trouvé cette question parce que vous avez rencontré la même erreur et que vous utilisez en fait Rails STI, mais que vous avez obtenu l'erreur parce que vous essayez de renommer les sous-classes héritées, c'est probablement parce que vous avez d'anciennes données dans la colonne type et j'ai oublié de le mettre à jour. Ensuite, cette tâche de râteau pourrait vous aider:

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
2
Magne

Vous pouvez définir à l'intérieur de votre modèle self.inheritance_column = :sti_disabled (ou un autre nom) si vous n'utilisez pas STI pour le modèle AR actuel

0
yozzz