Ruby-on-rails 无效的单表继承类型:Rails
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20357997/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Invalid single-table inheritance type: Rails
提问by Antarr Byrd
I'm getting this error when trying to create a new Product in my Rails application.
尝试在我的 Rails 应用程序中创建新产品时出现此错误。
Invalid single-table inheritance type: Movie is not a subclass of Product
单表继承类型无效:Movie 不是 Product 的子类
How can I resolve this?
我该如何解决这个问题?


controller
控制器
class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update, :destroy]
# GET /products
# GET /products.json
def index
@products = Product.all
end
# GET /products/1
# GET /products/1.json
def show
end
# GET /products/new
def new
@product = Product.new
end
# GET /products/1/edit
def edit
end
# POST /products
# POST /products.json
def create
@product = Product.new(product_params)
respond_to do |format|
if @product.save
format.html { redirect_to @product, notice: 'Product was successfully created.' }
format.json { render action: 'show', status: :created, location: @product }
else
format.html { render action: 'new' }
format.json { render json: @product.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /products/1
# PATCH/PUT /products/1.json
def update
respond_to do |format|
if @product.update(product_params)
format.html { redirect_to @product, notice: 'Product was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: @product.errors, status: :unprocessable_entity }
end
end
end
# DELETE /products/1
# DELETE /products/1.json
def destroy
@product.destroy
respond_to do |format|
format.html { redirect_to products_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_product
@product = Product.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def product_params
params.require(:product).permit(:title, :artist, :type, :release_date, :category, :publisher, :format, :description, :sale_price, :rental_price)
end
end
migration
移民
class CreateProducts < ActiveRecord::Migration
def change
create_table :products do |t|
t.string :title
t.string :artist
t.string :type
t.date :release_date
t.string :category
t.string :publisher
t.string :format
t.text :description
t.decimal :sale_price
t.decimal :rental_price
t.timestamps
end
end
end
回答by MrYoshiji
You should not use the typekeywordas the column name because it is a reserved word for ActiveRecord.
不应使用type关键字作为列名,因为它是 ActiveRecord 的保留字。
But if you really want to use it, for any reason (like if you don't have control on the DB structure), here is what you should do:
但是,如果您真的想使用它,无论出于何种原因(例如,如果您无法控制数据库结构),您应该执行以下操作:
First, make sure your Movie model inherits from the (false-)"abstract" model Product:
首先,确保您的 Movie 模型继承自 (false-)"abstract" 模型 Product:
class Product < ActiveRecord::Base
TYPES = %w( Movie )
before_save :set_type
validates :type, presence: true, :inclusion => { :in => TYPES }
def set_type
raiser "You must override this method in each model inheriting from Product!"
end
# ...
class Movie < Product
def set_type # If you don't implement this method, an error will be raised
self.type = 'Movie'
end
And then in your ProductsController you can manage (CRUD) all kind of products.
然后在您的 ProductsController 中,您可以管理(CRUD)所有类型的产品。
To add a new type of product:you just have to define a new Model inheriting from Product, implement it's set_type method and add the type in the product's Constant:
要添加新类型的产品:您只需要定义一个从 Product 继承的新模型,实现它的 set_type 方法并将类型添加到产品的常量中:
class Book < Product
def set_type
self.type = 'Book'
end
#...
class Product < ActiveRecord::Base
TYPES = %w( Movie Book )
回答by h4xnoodle
If you don't intend to create a model for your value for 'type', then what is likely happening is 'type' is a reserved word in ActiveRecord.
如果您不打算为“类型”的值创建模型,那么可能发生的情况是“类型”是 ActiveRecord 中的保留字。
See http://en.wikibooks.org/wiki/Ruby_on_Rails/ActiveRecord/Naming
请参阅http://en.wikibooks.org/wiki/Ruby_on_Rails/ActiveRecord/Naming
"type- This is only used when you have single table inheritance and must contain a class name"
“ type- 这仅在您具有单表继承且必须包含类名时使用”
回答by DDDD
Add self.inheritance_column = nilto your model. type is reserved.
添加self.inheritance_column = nil到您的模型中。类型被保留。
回答by Goulven
Another way is to name the column differently (product_typewould be fine here), and add an attribute alias alias_attribute :type, :product_typein your model definition.
另一种方法是以不同的方式命名列(product_type在这里很好),并alias_attribute :type, :product_type在模型定义中添加属性别名。
That way you can use @product.typesafely, because Rails will substitute product_typewhen you read from or write to the typeattribute.
这样您就可以@product.type安全地使用,因为 Rails 会product_type在您读取或写入type属性时进行替换。
Tested with Rails 4.1.2.
使用 Rails 4.1.2 测试。

