I have a folder named admin that has a generated scaffolding in it named products that also has the primary_key, id, changed to ect. I then created a model called cart_products that has a belongs_to :product
. When I try to use it like:
@cart.cart_products.create(product: @product, quantity:)
, it throws a name error, saying
Rails couldn't find a valid model for Product association. Please provide the :class_name option on the association declaration. If :class_name is already provided, make sure it's an ActiveRecord::Base subclass.
So I then changed the belongs_to to belongs_to :product, :class_name => "Admin::Product"
which is the name of the product model. Now I am getting an
ActiveRecord::StatementInvalid - SQLite3::SQLException: no such table: main.products
Where did main.products
come from when in my database it is saved as create_table "admin_products", primary_key: "ect", force: :cascade do |t|
?
This is what My code looks like:
# controllers/home/cart_controller.rb
class Home::CartController < HomeController
def add
@product = Admin::Product.find_by(ect: params[:ect])
# Code breaks on next line
@cart.cart_products.create(product: @product, quantity:)
end
end
# models/cart_product.rb
class CartProduct < ApplicationRecord
belongs_to :product, class_name: "Admin::Product"
belongs_to :cart
end
# models/admin/product.rb
class Admin::Product < ApplicationRecord
has_many :cart_products
has_many :carts, through: :cart_products
end
end
# models/admin.rb
module Admin
def self.table_name_prefix
"admin_"
end
end
The Database that I am trying to access is:
# associated with models/admin/product.rb
create_table "admin_products", primary_key: "ect", force: :cascade do |t|
t.string "title"
t.decimal "price"
t.text "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
# associated with models/cart_product.rb
class CreateCartProducts < ActiveRecord::Migration[7.0]
def change
create_table :cart_products do |t|
t.belongs_to :product, null: false, foreign_key: true
t.belongs_to :cart, null: false, foreign_key: true
t.integer :quantity
t.timestamps
end
end
end
CodePudding user response:
Always run after scaffolding with any model
rails db:migrate
CodePudding user response:
Is your model file admin/product.rb
class Admin::Product < ApplicationRecord
If yes, then you need to have class_name with associations as below
belongs_to :product, class_name: "Admin::Product"
CodePudding user response:
You have to tell rails the table name:
# app/models/admin/product.rb
module Admin
class Product < ApplicationRecord
self.table_name = "admin_products"
end
end
Or add prefix to every table for models in Admin module.
# app/models/admin.rb
module Admin
def self.table_name_prefix
"admin_"
end
end
Update
Rollback your CreateCartProducts
migrations and update it to fix foreign key constraint:
# NOTE: by default when foreign key constraint is created
# the name of the foreign table is inferred from
# the argument `:product`. There is no `products` table,
# which is why SQLite complains about it in the error;
# custom primary key has to be also specified.
# t.belongs_to :product, null: false, foreign_key: true
t.belongs_to :product, null: false,
foreign_key: { to_table: :admin_products, primary_key: "ect" }
Run migrations again. This should fix it.
Also, it's probably best to set up PostgreSQL for development. It would have raised an error when trying to run that migration, but SQLite seems to be ok with migration but complains later.
https://api.rubyonrails.org/classes/ActiveRecord/ModelSchema/ClassMethods.html#method-i-table_name