web-dev-qa-db-ja.com

ActiveRecord :: SubclassNotFound:単一テーブルの継承メカニズムがサブクラスを見つけられませんでした

私はRailsの初心者です。
次の2つのモデルCategoryおよびProductがあります:-

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コマンドを使用して2つの製品で2つの製品を作成しました

[#<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コマンドを使用して2つのカテゴリを作成しました

<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を上書きしてその情報に別の列を使用してください。

そこで何が問題なのですか?カテゴリと製品の関係を次のようにしたい
カテゴリhas_manyの製品と製品はカテゴリに属します。

43
mrudult

typeは制限されたWordであり、ActiveRecordモデルで列名として使用することはできません(STIを実行している場合を除く)。

94
Mike Szyndel

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

このtype予約語に関する私自身の問題の解決策を見つけようとしているときにこの投稿に出くわしたので、多分これは他の人を助けることができます。

私はmongodbからアクティブなレコードに移行する既存の完全なシステムで作業しているため、列の名前を変更するのは簡単な解決策ではありません。

self.inheritance_column = :_type_disabled問題のある列名を持つモデルに、私が見つけたエラーを修正しました here

STIを無効にする

これを機能させるには、単に「inheritance_column」ではなく「self.inheritance_column」を追加する必要がありました。コード例

class MyModel <ActiveRecord :: Base#STIを無効にします
self.inheritance_column =:_type_disabled end

私たちは継承を使用していないことを知っているので、これを行うことは問題ないと思いますが、そのために他にどのような影響があるのか​​わかりません。他の誰かがこれについて意見を持っているなら、私は知りたいと思うでしょう。

列名を変更するだけでこれを避けることができる場合、それははるかに優れたソリューションです。

13
Topher

誰かが実際にSTIを実行しようとしている場合は、親から継承する新しいクラスを追加してみてください。問題のエラーメッセージは消えます。

class YourSubclass < Category
end
3
s2t2

同じエラーが発生したためにこの質問を見つけて、実際に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
2
Magne

モデル内で設定できますself.inheritance_column = :sti_disabled(または他の名前)現在のARモデルにSTIを使用していない場合

0
yozzz