私は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の製品と製品はカテゴリに属します。
type
は制限されたWordであり、ActiveRecordモデルで列名として使用することはできません(STIを実行している場合を除く)。
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
この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
私たちは継承を使用していないことを知っているので、これを行うことは問題ないと思いますが、そのために他にどのような影響があるのかわかりません。他の誰かがこれについて意見を持っているなら、私は知りたいと思うでしょう。
列名を変更するだけでこれを避けることができる場合、それははるかに優れたソリューションです。
誰かが実際にSTIを実行しようとしている場合は、親から継承する新しいクラスを追加してみてください。問題のエラーメッセージは消えます。
class YourSubclass < Category
end
同じエラーが発生したためにこの質問を見つけて、実際に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
モデル内で設定できますself.inheritance_column = :sti_disabled
(または他の名前)現在のARモデルにSTIを使用していない場合