[英]Single Table Inheritance not working in Rails 4 app - ActiveRecord::SubclassNotFound: The single-table inheritance mechanism failed
[英]ActiveRecord::SubclassNotFound: The single-table inheritance mechanism failed to locate the subclass
我是 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 以使用另一列存儲該信息,請重命名此列。
里面有什么問題? 我想在類別和產品之間建立關系,例如
一個類別有_許多產品並且產品屬於_一個類別。
type
是受限制的詞,您不能將其用作 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
添加到具有違規列名的模型中修復了我在此處找到的錯誤。
禁用 STI
我必須添加“self.inheritance_column”而不是簡單的“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
如果當前 AR 模型未使用 STI,則可以在模型中設置self.inheritance_column = :_sti_disabled
(或其他名稱)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.