single references rails foreign belong association ruby-on-rails inheritance ruby-on-rails-4

ruby on rails - references - Tipo de herencia de tabla única no válida: Rails



relationship rails 5 (4)

Recibo este error al intentar crear un nuevo Producto en mi aplicación Rails.

Tipo de herencia de tabla única no válida: la película no es una subclase de Producto

¿Cómo puedo resolver esto?

controlador

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

migración

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


Agregue self.inheritance_column = nil a su modelo. tipo está reservado.


Otra forma es nombrar la columna de manera diferente ( product_type estaría bien aquí) y agregar un atributo alias alias_attribute :type, :product_type en la definición de su modelo.

De esta forma, puede usar @product.type forma segura, porque Rails sustituirá a product_type cuando lea o escriba en el atributo de type .

Probado con Rails 4.1.2.


Si no tiene la intención de crear un modelo para su valor para ''tipo'', entonces lo que probablemente está sucediendo es ''tipo'' es una palabra reservada en ActiveRecord.

Ver http://en.wikibooks.org/wiki/Ruby_on_Rails/ActiveRecord/Naming

" type - Esto solo se usa cuando tienes herencia de tabla única y debe contener un nombre de clase"


No debe usar la palabra clave type como el nombre de la columna porque es una palabra reservada para ActiveRecord .

Pero si realmente desea usarlo, por cualquier motivo (como si no tuviera control sobre la estructura de la base de datos), esto es lo que debe hacer:

Primero, asegúrese de que su modelo de película herede del modelo (abstracto) "abstracto" Producto:

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

Y luego en su ProductsController puede administrar (CRUD) todo tipo de productos.

Para agregar un nuevo tipo de producto: solo tiene que definir un nuevo Modelo que hereda del Producto, implementar su método set_type y agregar el tipo en la Constante del producto:

class Book < Product def set_type self.type = ''Book'' end #... class Product < ActiveRecord::Base TYPES = %w( Movie Book )