Je reçois cette erreur en essayant de créer un nouveau produit dans mon application Rails.
Type d'héritage à une seule table non valide: Movie n'est pas une sous-classe de Produit
Comment puis-je résoudre ça?
manette
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
Vous ne devez pas utiliser le mot clé type
comme nom de colonne car il s'agit d'un mot réservé pour ActiveRecord .
Mais si vous voulez vraiment l'utiliser, pour quelque raison que ce soit (comme si vous n'avez pas le contrôle sur la structure de la base de données), voici ce que vous devriez faire:
Tout d’abord, assurez-vous que votre modèle Movie hérite du modèle (abstrait) "abstrait".
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
Ensuite, dans votre ProductsController, vous pouvez gérer (CRUD) tout type de produit.
Pour ajouter un nouveau type de produit: , il vous suffit de définir un nouveau modèle héritant du produit, de mettre en œuvre sa méthode set_type et d'ajouter le type dans la constante du produit:
class Book < Product
def set_type
self.type = 'Book'
end
#...
class Product < ActiveRecord::Base
TYPES = %w( Movie Book )
Si vous n'avez pas l'intention de créer un modèle correspondant à votre valeur pour "type", il est probable que "type" correspond à un mot réservé dans ActiveRecord.
Voir http://fr.wikibooks.org/wiki/Ruby_on_Rails/ActiveRecord/Naming
"type
- Ceci n'est utilisé que lorsque vous avez l'héritage d'une table et que vous devez contenir un nom de classe"
Ajoutez self.inheritance_column = nil
à votre modèle. le type est réservé.
Une autre méthode consiste à nommer la colonne différemment (product_type
conviendrait ici) et à ajouter un alias d'attribut alias_attribute :type, :product_type
dans la définition de votre modèle.
De cette façon, vous pouvez utiliser @product.type
en toute sécurité, car Rails substituera product_type
lors de la lecture ou de l'écriture dans l'attribut type
.
Testé avec Rails 4.1.2.