I'm getting this error when trying to create a new Product in my Rails application.
Invalid single-table inheritance type: Movie is not a subclass of 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
You should not use the type
keyword as the column name because it is a reserved word for 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:
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.
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:
class Book < Product
def set_type
self.type = 'Book'
end
#...
class Product < ActiveRecord::Base
TYPES = %w( Movie Book )
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.
See 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"
Add self.inheritance_column = nil
to your model. type is reserved.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With